Express 的中间件
Express 的中间件,本质上就是一个 function 处理函数.
Express中间件的格式如下:
需要注意的是:中间件有三个参数。在中间件的形参列表中。
必须包含next参数;它既是参数也是函数。
其中路由处理函数中有req和res。
有的小伙伴可能会问呢?
我怎么知道是一个函数还是一个中间件。他们实在是长得太像了。
其实:我们可以通过第三个参数来判断是不是中间件。
next函数的作用
next 函数是实现多个中间件连续调用的关键,
它表示把流转关系转交给下一个中间件或路由。
我们可以理解为前端路由中路由守卫中的next。
中间件的调用流程
当一个请求到达 Express的服务器之后,
可以连续调用多个中间件,从而对这次请求进行[预处理]。
定义一个简单的中间件
// 常量 mw 所指向的,就是一个中间件函数
const mw = function (req, res, next) {
console.log("我是一个中间件')
// 注意: 在当前中间件的业务处理完毕后,必须调用 next() 函数
// 表示把流转关系转交给下一个中间件或路由next()
}
注册一个全局生效的中间件
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。
expres中通过调用 app.use(中间件函数),即可定义一个全局生效的中间件,代码如下:
//常量 mw 所指向的,就是一个中间件函数
const mw = function (req, res, next) {
console.log('这是一个最简单的中间件函数')
next()
}
// 全局生效的中间件
app.use(mw)
调用请求接口,全局中间件被触发
const express = require("express");
const app = express();
//常量 mw 所指向的,就是一个中间件函数
const mw = function (req, res, next) {
console.log('这是一个最简单的中间件函数,我将会被触发')
next()
}
// 全局生效的中间件
app.use(mw)
// 监听客户端的get请求
app.get('/user', (req, res) => {
res.send({name:'张三',age:22, type:'admin'})
})
app.listen(3000, () => {
console.log('express serve Started successfully')
})
在浏览器中输入 http://127.0.0.1:3000/user 会触发中间件
需要注意中间件的一个顺序问题
如果我们把中间件放在路由的后面。
这样中间件会失效的。
因为代码从上往下执行。路由都执行完了。就不关中间件什么事情了。
像下面这一种:把中间件放在路由后面。中间件将不会被执行
app.get('/user', (req, res) => {
res.send({name:'张三',age:22, type:'admin'})
})
const mw = function (req, res, next) {
console.log('这是一个最简单的中间件函数,我将会被触发')
next()
}
app.use(mw)
定义多个全局中间件
我么可以使用 app.use()连续定义多个全局中间件。
就像之前定义多个静态服务一样。
客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用。
代码如下:
//常量 mw 所指向的,就是一个中间件函数
const mw1 = function (req, res, next) {
console.log('我是第1个中间件')
next()
}
const mw2 = function (req, res, next) {
console.log('我是第2个中间件')
next()
}
// 全局生效的中间件1
app.use(mw1)
// 全局生效的中间件2
app.use(mw2)
局部生效的中间件
有的小伙伴可能会问,上面是全局中间件。
有没有局部中间件呢?
有的! 局部中间件是这样定义的:
不使用app.use()定义的中间件,叫做局部中间件。
也就是说:有app.use()的是全局中间件。没有app.use()定义的是局部中间件
const express = require("express");
const app = express();
//常量 mw1 所指向的,就是一个中间件函数
const mw1 = function (req, res, next) {
console.log('我是局部生效的中间件')
next()
}
// 监听客户端的get请求,局部中间件不会影响这个user请求
app.get('/user', (req, res) => {
res.send({name:'张三',age:22, type:'admin'})
})
// 当请求list的之后,这个中间件只会在list中生效
app.get('/list',mw1, (req, res) => {
res.send([{name:'张三',age:22, type:'admin'}])
})
app.listen(3000, () => {
console.log('express serve Started successfully')
})
04png
定义多个局部中间件
有些时候,我们针对某一个请求。
可能需要使用多个中间件。这个时候多个局部中间件就出场了。
下面是多个局部中间件的两种方式:
//定义了中间件mw1,mv2。使用逗号隔开:多个中间件
app.get('/list',mw1,mv2, (req, res) => {
res.send('我是list请求')
})
//定义了中间件mw1,mv2。把多个中间件放在一个数组中
app.get('/user',[mw1,mv2], (req, res) => {
res.send('我是list请求')
})
express 中间件的分类
Express 官方把常见的中间件用法,分成了 5 大类。
1.应用级别的中间件
2.路由级别的中间件
3.错误级别的中间件
4.Express 内置的中间件
5.第三方的中间件
应用级别的中间件
通过 app.use()或 app.get()或 app.post(),
绑定到 app 实例上的中间件,叫做应用级别的中间.
我们上面写的代码,就算是应用级别的中间件
路由级别的中间件
绑定到 express.Router()实例上的中间件,叫做路由级别的中间件。
它的用法和应用级别中间件没有任何区别。
只不过,应用级别中间件是绑定到 app 实例上.
路由级别中间件绑定到 router 实例上
错误级别的中间件
错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,
从而防止项目异常崩溃的问题。
下面我们抛出一个异常。
const express = require("express");
const app = express();
// 当请求 file 之后,虽然项目发生了错误,但是不会让项目崩掉
app.get('/file', (req, res) => {
res.send({info:'发生错误'})
throw new Error('服务器咋开小差')
})
//这中间件在路由后面。
app.use((err,req,res,next) => {
console.log('发生了错误:', err)
res.send('error:', err.message)
})
app.listen(3000, () => {
console.log('express serve Started successfully')
})
关于错误级别的中间件的特殊点
有的小伙伴看了上面的代码。发现很奇怪。
不是说的:
把中间件放在路由后面。中间件将不会被执行。
咋个还执行了呢?
因为:错误级别的中间件比较特殊。
必须注册在所有的路由之后。
Express 内置的中间件
自Express 4.16.0 版本开始,Express 内置了3 个常用的中间件.
1==> express.static 托管静态资源的内置中间件.
例如: HTML 文件、图片、CSS 样式等(无兼容性)
2==> express.json 解析JSON 格式的请求体数据 (有兼容性,仅在 4.16.0+ 版本中可用)
3==> express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)
// 配置解析 application/json 格式数据的内置中间件
app.use(express.json( ))
// 配置解析 application/x-w-form-urlencoded 格式数据的内置中间件
app.use(express.urlencoded({ extended: false }))
遇见问题,这是你成长的机会,如果你能够解决,这就是收获。
作者:晚来南风晚相识