中间件函数能够访问请求对象 (req)、响应对象 (res) 以及应用程序的请求/响应循环中的下一个中间件函数。下一个中间件函数通常由名为next
的变量来表示。
中间件函数可以执行以下任务:
- 执行任何代码。
- 对请求和响应对象进行更改。
- 结束请求/响应循环。
- 调用堆栈中的下一个中间件函数。
如果当前中间件函数没有结束请求/响应循环,那么它必须调用next()
函数,以将控制权传递给下一个中间件函数。否则,请求将保持挂起状态。
演示示例:
/**
* express 中间件使用解析
*/
const express = require('express')
// 本次 http 请求的实例
const app = express()
// 模拟登陆验证
function loginCheckSuccess(req, res, next) {
console.log('模拟登陆成功')
setTimeout(() => {
next()
})
}
// 模拟登陆失败
function loginCheckFailed(req, res, next) {
console.log('模拟登陆失败')
setTimeout(() => {
res.json({
errno: -1,
msg: '登陆失败'
})
})
}
app.use((req, res, next) => {
console.log('请求开始···', req.method, req.url)
next()
})
app.use((req, res, next) => {
// 假设在处理 cookie
req.cookie = {
userID: 'abc123'
}
next()
})
app.use((req, res, next) => {
// 假设处理 post data
// 异步
setTimeout(() => {
req.body = {
a: 100,
b: 200
}
next()
})
})
app.use('/api', (req, res, next) => {
console.log('处理 /api 路由')
next()
})
app.get('/api', (req, res, next) => {
console.log('get /api 路由')
next()
})
app.post('/api', (req, res, next) => {
console.log('get /api 路由')
next()
})
app.get('/api/get-cookie', loginCheckSuccess, (req, res, next) => {
console.log('get /api/get-cookie')
res.json({
errno: 0,
data: req.cookie
})
})
app.post('/api/get-post-deta', loginCheckFailed, (req, res, next) => {
console.log('post /api/get-post-data')
res.json({
error: 0,
data: res.body
})
})
app.use((req, res, next) => {
console.log('处理 404')
res.json({
error: -1,
msg: '404 not found'
})
})
app.listen(3000, () => {
console.log('server is running on 3000')
})
通过浏览器分析get请求
这里使用应用层中间件为例,解释中间件的使用
- 首先调用
app.use()
函数的中间件,将能够响应任何方法的请求。app.method()
函数将处理对应HTTP方法的请求 - 如果第一个参数没有传入路径参数,将默认解释为根路径(
/
) - 支持传入多个中间件函数,但为了提高代码的可读性,尽量不要超过三个
- 首先
nodex index.js
运行上面的代码 - 在浏览器中输入
localhost:3000/api/get-cookie
- 浏览器返回:
{"errno":0,"data":{"userID":"abc123"}}
我们再查看控制台中的输出
$ node index.js
server is running on 3000
请求开始··· GET /api/get-cookie
处理 /api 路由
模拟登陆成功
get /api/get-cookie
让我们来借此分析一下,中间件的运行。
首先,app.use((req, res, next)...
,这里是通过app.use
注册的,并且没有指定响应路由参数,默认为/
,将响应系统的所有路由和方式的请求,所以先输出了这里定义的回调函数(请求开始··· GET /api/get-cookie
)。
其次,是第二个使用app.use()
的定义的函数,定义了req.cookie
app.use((req, res, next) => {
// 假设在处理 cookie
req.cookie = {
userID: 'abc123'
}
next()
})
再次,由于我们访问的地址为/api/get-cookie
,这样会先访问到他的上级路径上定义的中间件函数,app.get('/api')
,所以紧接着输出了处理 /api 路由
。
最后,进入到app.get('/api/get-cookie')
定义的应用层中间件。首先依次执行loginCheckSuccess()
中间件函数,返回模拟登陆成功
,next()
,执行后面的中间件函数,res.json()
为服务器返回了req.cookie
中写入的值。
### 通过postman分析post请求
使用postman,在请求地址栏输入http://127.0.0.1:3000/api/get-post-deta
,将返回{"errno":-1,"msg":"登陆失败"}
其执行原理和通过浏览器测试get
请求类似,都是顺序执行了app.use
和app.post
的从根路径到目标路径上的中间件函数。不同的是,这里我们用loginCheckFailed()
函数模拟了登录失败,这样由于登录失败,直接向postman中返回错误信息,将不再执行后面的中间件函数。
网友评论