切换导航
简历
工具
演示
查询
导航菜单
服务端
30
前端
114
数据库
82
进阶开发
8
桌面程序
2
QA
15
软件使用
36
规范协议
5
操作系统
11
AI
0
复用资源
6
硬件
0
标签
HTML
正则表达式
Json
包管理工具
vite
CSS
XPath
JavaScript
Jquery
less
ES6
Vue
React
vue 3
Layui
editor.md
sea.js
Zepto.js
mysql.js
mssql.js
NodeJs
Express
前端template
YAML
杂项
外部链接
.NET Core SDK和运行时安装包
淘宝 NPM 镜像
查询网
Tables Generator线上表格转换工具
引用cdn在线脚本和样式
首页
前端
Express中间件
[TOC] ## Express中间件介绍 中间件是处理过程中的一个环节,本质上就是一个函数 ### next函数 next方法的作用就是把请求传递到下一个中间件,在整个请求过程中,res和req贯穿整个请求过程 ### 应用中间件 下面的代码示例中`use`的回调函数中有next参数则为一个中间件,函数体中都需要调用next()方法,将请求传递到下一个中间件,中间件的执行按照代码顺序执行,直到执行到没有next参数的方法为止 ```js const express = require("express"); const app = express(); let count = 0; //第一个use app.use((req, res, next) => { count = 1; next(); }) //第二个use app.use("/user", (req, res, next) => { count++; next(); }) //第三个use app.use("/user", (req, res, next) => { count++; next(); }) //第四个use app.use((req, res) => { count++; res.send("传递了" + count) + "次"; }) app.listen(3000, "localhost", () => { console.log("running……") }) ``` 上面示例中分析请求 + 请求地址1:http://localhost:3000 输出结果为`传递了2`,路由规则第一个`use`未找到匹配的中间件,直接走到了最后的`use`中 + 请求地址2:http://localhost:3000/user 输出结果为`传递了4`,此求情满足了所有`use`规则,逐个向下执行了4个`use` ### 路由中间件 路由也可以绑定中间件,执行的顺序也是按代码顺序执行,路由绑定除了多个中间件参数也可以直接绑定一个中间件数组,下面示例中第31行中就绑定了一个数组格式的多个中间件 ```js const express = require("express"); const app = express(); let msg = ""; app.use((req, res, next) => { msg += "进入了第一个use<br />"; next(); }) let first = function (req, res, next) { msg += "进入了第一个first路由<br />"; next() } let second = function (req, res, next) { msg += "进入了第二个second路由<br />"; next() } //路由中间件 app.get("/user", (req, res, next) => { msg += "进入了第一个路由<br />"; //next使用了route参数后,将不会在执行本路由后面的中间件了, //而是跳转到下一个任意声明的中间,本段代码就是下一个use(第二个user)中间件 next("route") }, (res, req, next) => { msg += "进入了第二个路由<br />"; next() }) app.use("/user", (req, res, next) => { msg += "进入了第二个use<br />"; next(); }) //路由绑定的混合中间件,中间件可以用数组的方式绑定 app.get("/user", [first, second], (req, res, next) => { msg += "进入了第三个混合路由<br />"; next() }, (res, req) => { msg += "路由结束传递<br />"; req.send(msg + "路由请求结束"); msg = ""; }) app.use((req, res) => { msg += "应用请求结束<br />"; res.send(msg); msg = ""; }) app.use("/user", (req, res, next) => { msg += "进入了第三个use<br />"; next(); }) app.listen(3000, "localhost", () => { console.log("running……") }) ``` 上面示例中分析请求 + 请求地址1:http://localhost:3000 输出结果 ``` 进入了第一个use 应用请求结束 ``` 从结果中可以看出,首先next执行不会进入到不符合路由规则的中间件中,然后执行到没有next参数的函数体时,即为终结这时需要告诉浏览器结束请求了,req.send()信息给浏览器,否则浏览器会一直处于等待中,直到超时后报错。 + 请求地址2:http://localhost:3000/user 输出结果 ``` 进入了第一个use 进入了第一个路由 进入了第二个use 进入了第一个first路由 进入了第二个second路由 进入了第三个混合路由 路由结束传递 路由请求结束 ``` 执行结果分析,next会进入到符合路由规则的中间件中,按代码顺序一直执行到没有next参数的函数,然后req.send()信息给浏览器,在next()函数中可以添加参数`route`,加了参数之后将不会再执行改路由后面的函数了,而是跳转到下一个定义的应用中间件或路由中间,`route`感觉是跳出本中间件 ### 错误中间件 #### 参数error 错误中间件就是比普通的中间件多了一个参数error,错误中间件也是逐层向下执行的,异常后会自动转入错误中间件中进行处理 ```js const express = require("express"); const app = express(); app.get('/', function (req, res) { throw new Error('我错了') }) app.use((err, req, res, next) => { console.log(err.stack) throw new Error('不 是我错了') }) app.use((err, req, res, next) => { console.error(err.stack) res.status(500).send('程序遇到了一些问题!') }) app.listen(3000, "localhost", () => { console.log("running……") }) ``` 请求地址:http://localhost:3000/ 会在终端输出的错误异常的信息 ``` Error: 我错了 at E:\***\***\Express\middle\middleOther.js:5:11 at Layer.handle [as handle_request] (E:\***\***\Express\node_modules\express\lib\router\layer.js:95:5) at next (E:\***\***\Express\node_modules\express\lib\router\route.js:144:13) at Route.dispatch (E:\***\***\Express\node_modules\express\lib\router\route.js:114:3) at Layer.handle [as handle_request] (E:\***\***\Express\node_modules\express\lib\router\layer.js:95:5) at E:\***\***\Express\node_modules\express\lib\router\index.js:284:15 at Function.process_params (E:\***\***\Express\node_modules\express\lib\router\index.js:346:12) at next (E:\***\***\Express\node_modules\express\lib\router\index.js:280:10) at expressInit (E:\***\***\Express\node_modules\express\lib\middleware\init.js:40:5) at Layer.handle [as handle_request] (E:\***\***\Express\node_modules\express\lib\router\layer.js:95:5) Error: 不 是我错了 at E:\***\***\Express\middle\middleOther.js:10:11 at Layer.handle_error (E:\***\***\Express\node_modules\express\lib\router\layer.js:71:5) at trim_prefix (E:\***\***\Express\node_modules\express\lib\router\index.js:326:13) at E:\***\***\Express\node_modules\express\lib\router\index.js:286:9 at Function.process_params (E:\***\***\Express\node_modules\express\lib\router\index.js:346:12) at next (E:\***\***\Express\node_modules\express\lib\router\index.js:280:10) at next (E:\***\***\Express\node_modules\express\lib\router\route.js:136:14) at Layer.handle [as handle_request] (E:\***\***\Express\node_modules\express\lib\router\layer.js:97:5) at next (E:\***\***\Express\node_modules\express\lib\router\route.js:144:13) at Route.dispatch (E:\***\***\Express\node_modules\express\lib\router\route.js:114:3) ``` #### 错误信息传递方式 next(err) 通过next函数可将异常信息传递给异常中间件 ```js app.get('/', function (req, res, next) { fs.readFile('/index.html', function (err, data) { if (err) { next(err) // 将读取文件的错误信息传递到错误中间件进行处理 } else { res.send(data) } }) }) ``` 请求地址:http://localhost:3000/ 会在终端输出异常抛出的堆栈信息 ``` ReferenceError: fs is not defined at C:\***\***\Express\middle\middleOther.js:5:5 at Layer.handle [as handle_request] (C:\***\***\Express\node_modules\express\lib\router\layer.js:95:5) at next (C:\***\***\Express\node_modules\express\lib\router\route.js:144:13) at Route.dispatch (C:\***\***\Express\node_modules\express\lib\router\route.js:114:3) at Layer.handle [as handle_request] (C:\***\***\Express\node_modules\express\lib\router\layer.js:95:5) at C:\***\***\Express\node_modules\express\lib\router\index.js:284:15 at Function.process_params (C:\***\***\Express\node_modules\express\lib\router\index.js:346:12) at next (C:\***\***\Express\node_modules\express\lib\router\index.js:280:10) at expressInit (C:\***\***\Express\node_modules\express\lib\middleware\init.js:40:5) at Layer.handle [as handle_request] (C:\***\***\Express\node_modules\express\lib\router\layer.js:95:5) Error: 不 是我错了 at C:\***\***\Express\middle\middleOther.js:16:11 at Layer.handle_error (C:\***\***\Express\node_modules\express\lib\router\layer.js:71:5) at trim_prefix (C:\***\***\Express\node_modules\express\lib\router\index.js:326:13) at C:\***\***\Express\node_modules\express\lib\router\index.js:286:9 at Function.process_params (C:\***\***\Express\node_modules\express\lib\router\index.js:346:12) at next (C:\***\***\Express\node_modules\express\lib\router\index.js:280:10) at next (C:\***\***\Express\node_modules\express\lib\router\route.js:136:14) at Layer.handle [as handle_request] (C:\***\***\Express\node_modules\express\lib\router\layer.js:97:5) at next (C:\***\***\Express\node_modules\express\lib\router\route.js:144:13) at Route.dispatch (C:\***\***\Express\node_modules\express\lib\router\route.js:114:3) ``` ### 静态文件中间件 `express.static()`就是静态文件中间件函数,通过`app.use`挂载,静态文件挂载有两种形式 + 第一种使用别名,使用别名挂在时需要注意别名前面要加斜杠`/` - 示例:<mark>app.use("/static", express.static('public'))</mark>,public存放了css和js等静态文件 - 引用:<mark><link rel="stylesheet" href="/static/css/test.css"></mark>使用/static代替public文件夹 + 第二种直接挂载 - 示例:<mark>app.use(express.static('public'))</mark>,public存放了css和js等静态文件 - 引用:<mark><link rel="stylesheet" href="/css/test.css"></mark>直接省略了public目录 ```js const express = require('express') const app = express(); //使用了别名挂在静态文件,引用时需以/static开头,下面的public是存放静态资源的文件夹 app.use("/static", express.static('public')) let server = app.listen("3000", 'localhost', () => { console.log(server.address().address + server.address().port + ":服务已启动") }) ``` ### urlencoded参数解析 Express v4.16.0 之后自身支持urlencoded中间件了,无需引用body-parser第三方中间件了 详细使用与[🔎body-parser的urlencoded](http://www.cylyccjy.com/blog/info-md.html/8AA35C0276E6659B?type=39#h3-urlencoded-)一致 ### json参数解析 Express v4.16.0 之后自身支持json中间件了,无需引用body-parser第三方中间件了 详细使用与[🔎body-parser的json](http://www.cylyccjy.com/blog/info-md.html/8AA35C0276E6659B?type=39#h3-json-)一致 ### raw参数解析 Express v4.17.0 之后自身支持raw中间件了,无需引用body-parser第三方中间件了 详细使用与[🔎body-parser的raw](http://www.cylyccjy.com/blog/info-md.html/8AA35C0276E6659B?type=39#h3-raw-)一致 ### text参数解析 Express v4.17.0 之后自身支持text中间件了,无需引用body-parser第三方中间件了 详细使用与[🔎body-parser的text](http://www.cylyccjy.com/blog/info-md.html/8AA35C0276E6659B?type=39#h3-text-)一致
扫一扫手机看
点击排行
windows 文件资源管理器使用
Layui 弹窗open使用说明
SQL Server 中字符串函数使用
C# 使用QQ邮箱代理做邮件接收功能
SQL Server关于apply的两种形式cross apply 和 outer apply
ASP.NET MVC 模型的自定义验证
nvm安装及常用命令
SQL Server 中数据类型转换
SQL Server 中WITH AS短语的使用
IE浏览器下AJAX缓存问题导致数据不更新的解决办法
订阅号