Express 的中间件

使用 express 处理请求的时候,一般都在后面添加个回调,每个回调都包含req、res和next。而这一个个回调函数就是我们要学的中间件。

利用中间件我们可以做什么事情呢?

  1. 执行这任意代码。
  2. 更改请求对象和响应对象。
  3. 结束请求-响应周期。
  4. 调用堆栈中的下一个中间件函数。

如果当前中间件函数没有结束请求-响应周期,它必须调用 next() 将控制传递给下一个中间件函数。否则,请求将被挂起。

下图显示了中间件函数调用的元素:

从Express 5开始,返回 Promise 的中间件函数将在 reject 或抛出错误时调用 next(value)。next 将被调用,并返回被拒绝的值或抛出的错误。

关于中间的分类有哪些呢?

  1. 应用层的中间件:其实我们可以写包含req、res和next的一个函数,然后通过app.use注册一下,这样它就算一个应用层的中间件了。在请求处理的过程中,它就会被执行。
  2. 路由器级中间件:Express 的路由
  3. 错误处理中间件:Express 的错误处理
  4. 内置中间件:例如express.json()、express.urlencoded()等
  5. 第三方中间件:社区下载的中间件

不管分多少类,本质上都是包含req、res和next的回调。

关于中间件的调用,它永远先调用第一个匹配的中间件,调用完成后,看有没有next()去连接下一个中间件,没有的话就挂起,有就一直执行下去。

连续使用中间件的时候,通常把响应放在最后一个中间件。

javascript 复制代码
const express = require('express');
const app = express();
const port = 3000;

const middleware1 = (req, res, next) => {
    console.log('middleware1')
    next()
}
const middleware2 = (req, res, next) => {
    console.log('middleware2')
    next()
}
const middleware3 = (req, res, next) => {
    console.log('middleware3')
    next()
}

app.use(middleware1)
app.use(middleware2)
app.use(middleware3)

app.get('/', function (req, res, next) {
    console.log('express')
    res.json('express')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

// 打印结果
middleware1
middleware2
middleware3
express

如果我想往请求里添加参数,怎么做?

javascript 复制代码
const express = require('express');
const app = express();
const port = 3000;

const middleware = (req, res, next) => {
    req.name = 'jiawei'
    req.age = 18
    next()
}

app.use(middleware)

app.get('/info', function (req, res, next) {
    console.log('req.name:', req.name)
    console.log('req.age:', req.age)
    res.json('express')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

Postman请求 localhost:3000/info,打印结果

javascript 复制代码
req.name: jiawei
req.age: 18

如果是只想往特定的请求里添加数据呢?

javascript 复制代码
const express = require('express');
const app = express();
const port = 3000;

const middleware = (req, res, next) => {
    req.name = 'jiawei'
    req.age = 18
    next()
}

// app.use(middleware)

app.get('/info', function (req, res, next) {
    console.log('req.name:', req.name)
    console.log('req.age:', req.age)
    res.json('express')
})

app.get('/user', middleware, function (req, res, next) {
    console.log('req.name:', req.name)
    console.log('req.age:', req.age)
    res.json('express')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

这时,Postman 请求 localhost:3000/info,结果如下

javascript 复制代码
req.name: undefined
req.age: undefined

而 Postman 请求 localhost:3000/user,结果如下

javascript 复制代码
req.name: jiawei
req.age: 18
相关推荐
子兮曰5 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
前端小万5 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋5 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
伞伞悦读5 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
卡布鲁5 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
C语言小火车5 天前
C/C++ 为什么需要编译器?
开发语言·c++
李少兄5 天前
JavaScript 隐式全局变量解析
javascript