Express中间件(上)

345 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情 next 函数的作用

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

image.png

Express中间件的demo

定义中间件函数

可以通过如下的方式,定义一个最简单的中间件函数:

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

全局生效的中间件

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

通过调用 app.use(中间件函数),即可定义一个全局生效的中间件,示例代码如下:

const express = require('express')
const userRouter = require('./router')
const app = express()
// 常量 mw 所指向的,就是一个中间件函数
const mw = function (req, res, next) {
    console.log('这是一个简单的中间件函数');
    // 注意:在当前中间件的业务处理完毕后,必须调用 next() 函数
    // 表示把流转关系转交给下一个中间件或路由
    next()
}
​
// 全局生效的中间件
// 注意:注册中间件在路由前注册
app.use(mw)
​
// 使用 app.use() 注册路由模块
app.use(userRouter)
​
app.listen(8080, () => {
    console.log('server is running');
})

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

const express = require('express')
const userRouter = require('./router')
const app = express()
​
// 全局生效的中间件
// 注意:注册中间件在路由前注册
app.use(function (req, res, next) {
    console.log('这是一个简单的中间件函数');
    // 注意:在当前中间件的业务处理完毕后,必须调用 next() 函数
    // 表示把流转关系转交给下一个中间件或路由
    next()
})
​
// 使用 app.use() 注册路由模块
app.use(userRouter)
​
app.listen(8080, () => {
    console.log('server is running');
})

中间件的作用

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

image.png 定义多个全局中间件

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

app.use(function (req, res, next) {
    console.log('调用了第一个全局中间件');
    // 注意:在当前中间件的业务处理完毕后,必须调用 next() 函数
    // 表示把流转关系转交给下一个中间件或路由
    next()
})
​
app.use(function (req, res, next) {
    console.log('调用了第二个全局中间件');
    // 注意:在当前中间件的业务处理完毕后,必须调用 next() 函数
    // 表示把流转关系转交给下一个中间件或路由
    next()
})

局部生效的中间件

不使用 app.use() 定义的中间件,叫做局部生效的中间件,示例代码如下:

// 定义中间件函数 mw1
const mw1 = function (req, res, next) {
    console.log('这是中间件函数')
    next()
}
​
// mw1 这个中间件只在当前路由中生效, 这种用法属于"局部生效的中间件"
app.get('/', mw1, function (req, res) {
    res.send('home page.')
})
​
// mw1 这个中间件不会影响下面这个路由
app.get('/user', function (req, res) {
    res.send('User page.')
})

定义多个局部中间件

可以在路由中,通过如下两种等价的方式,使用多个局部中间件:

// 以下两种写法是完全等价的,可根据自己的喜好,选择任意一种方法进行使用
app.get('/', mw1, mw2, (req, res) => { res.send('Home page') })
app.get('/', [mw1, mw2], (req, res) => { res.send('Home page') })

了解中间件的5个使用注意事项

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

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

③ 执行完中间件的业务代码之后,不要忘记调用 next() 函数

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

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

中间件的分类

为了方便大家理解和记忆中间件的使用,Express 官方把常见的中间件用法,分成了 5 大类,分别是:

① 应用级别的中间件

② 路由级别的中间件

③ 错误级别的中间件

④ Express 内置的中间件

⑤ 第三方的中间件

应用级别的中间件

通过 app.use() 或 app.get() 或 app.post() ,绑定到 app 实例上的中间件,叫做应用级别的中间件,代码示例如下:

// 应用级别的中间件 (全局中间件)
app.use((req, res, next) => {
    next()
})
​
// 应用级别的中间件 (局部中间件)
app.get('/', mw1, (req, res) => {
    res.send('Home page')
})