一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
什么是中间件
中间件是指业务流程的中间处理环节
Express 中间件的调用流程
当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理
Express 中间件的格式
-
Express 的中间件,本质上就是一个
function()处理函数,Express 中间件的格式如下app.get('/',function(req,res,next)){ next(); } -
中间件函数的形参列表中,必须包含
next参数,而路由处理函数中只包含res和req
next 函数的作用
next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个 中间件 或 路由
定义中间件函数
在当前中间件的业务处理完毕后,必须调用 next() 函数,表示把流转关系转交给下一个中间件或路由
const mw = function (req, res, next) {
console.log('这是一个 中间件')
//业务处理。。。
next()
}
全局生效的中间件
-
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫作全局生效中间件
-
通过调用
app.use(中间件函数),即可定义一个全局生效的中间件 -
示例
const express = require('express') const app = express() const mw = function (req, res, next) { console.log('这是一个 中间件') next() } // 将 mw 注册为全局生效的中间件 app.use(mw) app.listen(80, ()=> { console.log('express 服务器运行在 http://127.0.0.1.80') })log:
-
定义全局中间件的简化形式
app.use(function (req, res, next) { console.log('这是一个 中间件') next() })
定义多个全局中间件
可以使用 app.use() 连续定义多个全局中间件,客户端请求到达服务器之后,会按照中间件定义的先后顺序一次进行调用
const express = require('express')
const app = express()
app.use(function (req, res, next) {
console.log('调用了第1个全局中间件')
next()
})
app.use(function (req, res, next) {
console.log('调用了第2个全局中间件')
next()
})
app.get(`/`, (req, res) => {
res.send('home page ')
})
app.listen(80, ()=> {
console.log('express 服务器运行在 http://127.0.0.1.80')
})
log:
局部生效的中间件
不使用 app.use() 定义的中间件,叫做局部生效中间件
const express = require('express')
const app = express()
// 定义一个中间件函数
const mw1 = function(req, res, next) {
console.log('这是中间件函数')
next()
}
// mw1 中间件只会在当前路由中生效
app.get('/', mw1, function(req, res){
console.log('经过中间件')
console.log('home pag')
res.send('home page')
})
// mw1 中间件不会影响这个路由
app.get('/user', function(req, res){
console.log('不经过中间件')
console.log('user page')
res.send('user page')
})
app.listen(80, ()=> {
console.log('express 服务器运行在 http://127.0.0.1.80')
})
log:
定义多个局部中间件
-
在路由中,可以使用多个局部中间件,以下俩种方式等价
app.get('/', mw1,mw2, (req, res) => { }) app.get('/', [mw1,mw2], (req, res) => { }) -
示例
const express = require('express') const app = express() const mw1 = function(req, res, next) { console.log('第1个中间件函数') next() } const mw2 = function(req, res, next) { console.log('第2个中间件函数') next() } app.get('/', mw1,mw2, (req, res) => { console.log('home page') res.send('home page') }) app.listen(80, ()=> { console.log('express 服务器运行在 http://127.0.0.1.80') })log:
中间件的作用
-
多个中间件之间,共享同一份
req和res。基于这样的特性,可以在上游的中间件中,统一为req和res对象添加自定义的属性或方法,供下游的中间件或路由使用 -
示例(获取每次请求到达的时间)
-
不使用中间件,每个路由都需添加时间
const express = require('express') const app = express() app.use(function (req, res, next) { next() }) app.get(`/`, (req, res) => { // 添加时间 const time = Date.now() res.send('home page ' + time) }) app.get(`/user`, (req, res) => { // 添加时间 const time = Date.now() res.send('user page ' + time) }) app.listen(80, ()=> { console.log('express 服务器运行在 http://127.0.0.1.80') }) -
使用中间件,统一在中间件中添加时间
const express = require('express') const app = express() app.use(function (req, res, next) { const time = Date.now() // 为 req 对象挂载自定义属性,从而把时间共享给后面的所有路由 req.startTime = time next() }) app.get(`/`, (req, res) => { res.send('home page ' + time) }) app.get(`/user`, (req, res) => { res.send('user page ' + time) }) app.listen(80, ()=> { console.log('express 服务器运行在 http://127.0.0.1.80') })
-
中间件的5个使用注意事项
- 一定要在路由之前注册中间件
- 客户端发送过来的请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务代码之后,不要忘记调用
next()函数 - 为了防止代码逻辑混乱,调用
next()函数后不要再写额外的代码 - 连续调用多个中间件时,多个中间件之间,共享
req和res对象