Node.js基础---Express中间件

news2024/12/23 22:09:59

1. 概念

1.什么是中间件

        中间件(Middleware),特指业务流程的中间处理环节

2. Express 中间件的调用流程

        当一个请求到达 Express 的服务器后,可以连续调用多个中间件,从而对这次请求进行预处理

3. Express 中间件格式

       Express 的中间件,本质上是一个 function 处理函数,Express 中间件格式如下

        中间件函数的形参列表中,必须包含 next 参数,而路由处理函数中只包含 req 和 res

4. next 函数的作用

        next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或者路由

2. 中间件函数

1. 定义

// 常量 mv 所指向的就是一个中间件函数
const mv = function ( req, res, next) {
    console.log('中间件demo')
    // 注意: 在当前中间件的业务处理完毕后,必须调用 next() 函数
    // 表示把流转关系转交给下一个中间件或路由
    next()
}

2. 全局生效的中间件

        客户端发起的任何请求,到达服务器后,都会触发的中间件,叫全局生效的中间件

        通过调用 app.use(中间件函数),即可定义一个全局生效的中间件

// 常量 mv 所指向的就是一个中间件函数
const mv = function ( req, res, next) {
    console.log('中间件demo')
    next()
}

// 全局生效的中间件
app.use(mv)

3. 定义全局中间件的简化形式

// 全局生效的中间件
app.use(function (req, res, next){
    console.log('demo')
    next()
})

4. 中间件的作用

        多个中间件之间,共享同一份 req 和 res,基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用

5. 定义多个全局中间件

        可以使用 app.use() 连续定义多个全局中间件,客户端请求到达服务器后,会按照中间件定义的先后顺序依次进行调用

6. 局部生效的中间件

        不使用 app.use() 定义的中间件,即局部生效的中间件

        只在当前路由生效

const mv1 = function(req, res, next) {
    console.log('中间件函数')
    next()
}

// mv1 中间件只在当前路由生效
app.get('/', mv1, function(req, res) {
    res,send('get')
})

// 此路由不生效
app.get('/user', function(req, res) {
    res,send('get1')
})

7. 定义多个局部中间件

        两种等价方式定义

app.get('/', mv1, mv2, function(req, res) { res,send('get') })
app.get('/', [mv1, mv2], function(req, res) { res,send('get') })

8. 中间件的5个使用注意事项

        ①  一定要在路由之前注册中间件

        ②  客户端发送的请求,可以连续调用多个中间件进行处理

        ③  执行完中间件的业务代码,需要调用 next() 函数

        ④  防止代码逻辑混乱,调用完 next() 函数后不要再写额外代码 

        ⑤  连续多个中间件时,多个中间件之间,共享 req 和 res 对象

3. 中间件的分类

        Express 官方把常见的中间件用法,分为了五大类

                ①  应用级别的中间件

                ②  路由级别的中间件

                ③  错误级别的中间件

                ④  Express 内置的中间件

                ⑤  第三方的中间件

1. 应用级别的中间件

        通过 app.use() 或 app.get() 或 app.post()绑定到app实例上的中间件,叫做应用级别的中间件        全局中间件和局部中间件

// 应用级别的中间件 (全局中间件)
app.use((req, res, next) => {
    next()
})

// 应用级别的中间件 (局部中间件)
app.get('/', mv1, (req, res, next) => {
    res.send('局部')
})

2. 路由级别的中间件 

        绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件,它的用法和应用级别中间件没有区别,区别在于,应用级别中间件是绑定在 app 实例上的,路由级别中间件绑定到 router 实例上的

const app = express()
const router = express.Router()

// 路由级别的中间件
router.use(function (req, res, next) {
    console.log('路由级别中间件')
    next()
})

app.use('/', router)

3. 错误级别的中间件

        作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题

        格式:必须要有 4 个形参,从前到后分别是 (err, req, res, next)

app.get('/', function(req, res) {            // 路由
    throw new Error('错误!')                 // 抛出自定义错误
    res.send('get')
})
app.use(function (err, req, res, next) {    // 错误级别的中间件        
    console.log('发生了错误' + err.message)  // 服务器打印错误消息
    res,send('Error' + err.message)         // 向客户端响应错误信息相关内容
})

        注意:错误级别的中间件,必须注册在所有路由之后

4. Express内置的中间件

        Express 4.16.0版本后,Express 内置了3个常用的中间件

        ①  express.static 快速托管静态资源的内置中间件,例如:HTML文件,图片,css样式(无兼容性

        ②  express.json 解析JSON格式的请求体数据(有兼容性,在4.16.0+版本可用)

        ③  express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,在4.16.0+版本可用)

// 配置解析 application/json 格式数据的内置中间件
app.use(express.json())
// 配置解析 application/x-www-form-urlencode 格式数据的内置中间件
app.use(express.urlencoded({ extend: false }))

5. 第三方的中间件

        非 Express 官方内置的,是第三方开发出来的中间件,叫第三方中间件,项目中可以按需下载并配置第三方中间件

        在 express@4.16.0 之前的版本中,经常使用 body-parser 第三方中间件来解析请求体数据:

        ①  运行 npm i body-parser 安装

        ②  使用 require 导入中间件

        ③  调用 app.use() 注册并使用中间件

        注意:Express 内置的 express.urlencoded 中间件,就是基于 body-parser 进一步封装的

4.  自定义中间件

1. 需求描述与实现步骤

        需求:手动模拟类似于 express.urlencoded 的中间件,解析POST提交到服务器的表单数据

        实现步骤:

                ①   定义中间件

                ②   监听 req 的 data 事件

                ③   监听 req 的 end 事件

                ④   使用 queryString 模块解析请求体数据

                ⑤   将解析出来的数据对象挂载为 req.body

                ⑥   将自定义中间件封装为模块

2. 定义中间件

        使用 app.use() 定义全局生效的中间件

app.use(function(req, res, next){
    // 中间件的业务逻辑
})

3. 监听 req 的 data 事件

        获取客户端发送到服务器的数据

        如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以data事件可能会触发多次,每次触发。获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接

// 定义变量 储存客户端发来的请求体数据
let str = ''
// 监听 req 对象的 data 事件
req.on('data', (chunk) => {
    // 拼接请求体数据,隐式转换为字符串
    str += chunk
})

4. 监听 req 的 end 事件

        请求体数据接收完毕之后会自动触发 req 的 end 事件

        可以在 req 的 end 事件中,拿到并处理完整的请求体数据

// 监听 req 对象的 end 事件
req.on('end', () => {
    console.log(str) // 打印完整请求体数据
    // TOOD: 把字符串的请求体数据,解析成对象格式
})

5. 使用 queryString 模块解析请求体数据

        Node.js 内置了一个 querystring 模块,专门用来处理查询字符串。通过这个模块提供的 parse(), 可以把查询字符串解析成对象的格式

// 导入处理 querystring 的 Node.js 内置模块
const qs = require('querystring')

// 调用 qs.parse() 方法 把查询字符串解析为对象
const body = qs.parse(str)

        注意:qs被弃用

6. 将解析出来的数据对象挂载为 req.body

        上游中间件和下游中间件及路由之间,共享同一份 req 和 res。可以将解析出来的数据,挂载为 req 的自定义属性,命名为 req.body,供下游使用

req.on('end', () => {
    const body = qs.parse(srt)    // 调用 qs.parse() 方法把查询字符串解析成对象
    req.body = body               // 解析出来的请求体对象瓜子
    next()                        // 调用 next(),执行后续逻辑
})    

7. 将自定义中间件封装为模块

        优化结构,封装为独立模块

// custom-body-parser.js 模块代码
const qs = require('querystring')
function bodyParser(req, res, next){ /* 省略 */ }
module.export = bodyParser // 向外导出解析请求体孙书记的中间件函数

---------------------------------------------

// 1. 导入自定义的中间件模块
const myBodyParser = require('custom-body-parse')
// 2. 注册自定义的中间件模块
app.use(myBodyParser )

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1482701.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker技术概论(1):Docker与虚拟化技术比较

Docker技术概论(1) Docker与虚拟化技术比较 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https:…

鸿蒙学习day1基础语法 基础变量类型

在这里插入图片描述 什么是变量:变量就是一些数据 如125,‘字符串数据’ 通过一个符号来表示 变量的定义 方法 let 变量名:变量类型 ’ 各种数据’ ,let是关键字,系统给的用来定义变量的 let name: string 张亚洲; let age: …

MATLAB中function_handle函数用法

目录 说明 创建对象 示例 命名函数求积分 匿名函数求积分 function_handle函数所表示的是函数的句柄。 说明 函数句柄是一种表示函数的 MATLAB 数据类型。函数句柄的典型用法是将函数传递给另一个函数。例如,可以将函数句柄用作基于某个值范围计算数学表达式的…

Mybatis 主从表有名字相同,只能查询出一条数据

Mybatis 主从表有名字相同,只能查询出一条数据 重新命名后,可以正常查询

网络爬虫部分应掌握的重要知识点

目录 一、预备知识1、Web基本工作原理2、网络爬虫的Robots协议 二、爬取网页1、请求服务器并获取网页2、查看服务器端响应的状态码3、输出网页内容 三、使用BeautifulSoup定位网页元素1、首先需要导入BeautifulSoup库2、使用find/find_all函数查找所需的标签元素 四、获取元素的…

AI-数学-高中-29-样本的数字特征(标准差、方差)

原作者视频:【统计】【一数辞典】3样本的数字特征_哔哩哔哩_bilibili 标准差(s)、方差(S^2)公式:判断数据的稳定性。

137.乐理基础-协和音程、不协和音程

内容参考于: 三分钟音乐社 上一个内容:136.旋律音程、和声音程、自然音程、变化音程 上一个内容里练习的答案: 所有音程都可以分成协和音程与不协和音程两大类 协和音程又分三个小类: 第一个小类叫极完全协和音程,就…

特殊设计模式

▶实现一个类,不能被拷贝 ▶实现一个类,只能在堆上创建 ❗实现一个类,只能创建在栈上 ❗设计一个不能继承的类 ❗单例模式——一个类只能生成一个对象   ❔饿汉模式——在每次程序启动都会自动生成一个对象   ❓懒汉模式——在第一次需要…

202435读书笔记|《半小时漫画中国史》——读点经济学与历史,生活更美好,趣味烧脑土地制度、商鞅变法、华丽丽的丝绸之路这里都有

202435读书笔记|《半小时漫画中国史》——读点经济学与历史,生活更美好,趣味烧脑土地制度、商鞅变法、华丽丽的丝绸之路这里都有 1. 土地政策、度量衡及税收2. 商鞅变法3. 西汉经济4. 西汉盐铁大辩论5. 西汉丝绸之路 《半小时漫画中国史:经济…

​MPV,汽车产品里一个特殊品类的进化过程

「汽车」可能是整个工业革命以来,所诞生出的最有趣的工业产品。 它不仅能产生工业的机械美,还诞生了一个独立的文化体系,在汽车的发展过程中,我们也能看到一些本来应功能而诞生的产品,最终走向了千家万户。 MPV 就是…

Qt5.9.9交叉编译(带sqlite3、OpenSSL)

1、交叉编译工具链 这里ARM平台是ARM CortexA9的,一般交叉编译工具链demo板厂商都会提供,若未提供或想更换新版本的交叉编译工具链可参考以下方式获取。 1.1 下载适用于ARM CortexA9的交叉编译工具链 Linaro Releases下载gcc4的最新版xxxx-i686_arm-li…

使用 Docker 部署 Fiora 在线聊天室平台

一、Fiora 介绍 Fiora 简介 Fiora 是一款开源免费的在线聊天系统。 GitHub:https://github.com/yinxin630/fiora Fiora 功能 注册账号并登录,可以长久保存你的数据加入现有群组或者创建自己的群组,来和大家交流和任意人私聊,并添…

Cocos Creator 3.8.x 后效处理(前向渲染)

关于怎么开启后效效果我这里不再赘述,可以前往Cocos官方文档查看具体细节:后效处理官网 下面讲一下怎么自己定义一个后处理效果,想添加自己的后效处理的话只需要在postProcess节点下添加一个BlitScreen 组件即可,然后自己去添加自…

ElasticSearch搜索引擎使用指南

一、ES数据基础类型 1、数据类型 字符串 主要包括: text和keyword两种类型,keyword代表精确值不会参与分词,text类型的字符串会参与分词处理 数值 包括: long, integer, short, byte, double, float 布尔值 boolean 时间 date 数组 数组类型不…

div在vue的组件之中如何设置这个字体的颜色和样式大小

在Vue组件中设置<div>的字体颜色和样式大小可以通过两种主要方式实现&#xff1a;通过内联样式&#xff08;inline styles&#xff09;或者通过CSS类&#xff08;CSS classes&#xff09;。 使用内联样式 在Vue模板中直接在元素上使用style属性来设置样式。这种方法适用…

2024年春招小红书前端实习面试题分享

文章目录 导文面试重点一、方便介绍一下&#xff0c;你之前实习都做了什么嘛&#xff1f;二、 可以讲一下封装组件相关逻辑嘛&#xff1f;1. 为什么要封装组件&#xff1f;2. 封装组件的步骤3. 封装组件的原则4. 组件的复用和扩展5. 组件的维护和文档 三、项目的性能优化你有什…

Apache Echarts介绍与入门

介绍 Apache ECharts 是一款基于 Javascript 的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表。 官网地址&#xff1a;https://echarts.apache.org/zh/index.html 入门案例 Apache Echarts官方提供的快…

大数据智能化-长视频领域

随着数字化时代的到来&#xff0c;长视频领域的发展迎来了新的机遇和挑战。在这一背景下&#xff0c;大数据智能化技术的应用成为长视频行业提升用户体验、优化运营管理的重要手段之一。本文将从优爱腾3大长视频背景需求出发&#xff0c;分析静态资源CDN、视频文件存储与分发、…

midjourney提示词语法

更高级的提示可以包括一个或多个图像URL、多个文本短语和一个或更多个参数 Image Prompts 可以将图像URL添加到提示中&#xff0c;以影响最终结果的样式和内容。图像URL总是位于提示的前面。 https://docs.midjourney.com/image-prompts Text Prompt 要生成的图像的文本描述。…

[法规规划]国家数据局局长刘烈宏《激活数据要素价值》演讲要点解析

国家数据局党组书记、局长刘烈宏在北大光华论坛上发表了题为《激活数据要素价值》的演讲&#xff0c;当时曾极大推动了市场热度&#xff0c;引发了行业思考。现在演讲过去了一段时间&#xff0c;但是温故而知新&#xff0c;我们不妨结合演讲之后的市场反应&#xff0c;回顾一下…