网站首页 > 开源技术 正文
不知道用了express.js的你有没有这样的疑问:
- app.use为什么可以添加一个又一个中间件?
- connect是如何区分普通中间件和错误中间件的?
- 中间件处理函数中的next指代的又是什么?
我简单看了一下connect源码,弄清楚了上面的这3个问题。
app.use为什么可以添加一个又一个中间件?
app.use(function middleware1(req, res, next) {
// middleware 1
next();
});
app.use(function middleware2(req, res, next) {
// middleware 2
next();
});
connect维护了一个中间件栈(middleware stack)
数据结构:栈(stack)
每次调用use,都会向这个应用(app)实例的栈(stack)推入一个带路径和处理函数的对象。
源码:
function createServer() {
function app(req, res, next){ app.handle(req, res, next); }
// ...
app.stack = []; // 注意这里
return app;
}
proto.use = function use(route, fn) {
var handle = fn;
var path = route;
// ...
// add the middleware
this.stack.push({ route: path, handle: handle });
return this;
};
connect是如何区分普通中间件和错误中间件的?
// regular middleware
app.use(function (req, res, next) {
next(new Error('boom!'));
});
// error middleware
app.use(function onerror(err, req, res, next) {
// an error occurred!
});
JavaScript的函数的长度属性:length。
这么说可能比较绕,看下面这个例子就懂了。
例如
function test1(foo,bar){ }
test.length // 2
function test2(foo,bar,baz){ }
test.length // 3
connect正是通过中间件处理函数的形参长度来区分出普通中间件和错误中间件的。
function call(handle, route, err, req, res, next) {
var arity = handle.length;
var error = err;
var hasError = Boolean(err);
try {
if (hasError && arity === 4) {
// error-handling middleware
handle(err, req, res, next);
return;
} else if (!hasError && arity < 4) {
// request-handling middleware
handle(req, res, next);
return;
}
} catch (e) {
// replace the error
error = e;
}
// continue
next(error);
}
看了源码,官方文档对错误处理中间件描述skipping any error middleware above that middleware and any non-error middleware below的解释其实也懂了:
- 跳过前面的所有错误中间件:index值是递增的,请求只走后面的错误中间件
- 跳过后面的非异常处理中间件:异常中间件两个条件都满足请求会进入,非异常中间件由于hasError为true因此请求不会进入
只能有一个异常处理中间件吗? 可以有多个。(官方文档+亲测)
app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)
// error middleware one
app.use(function onerror(err, req, res, next) {
// an error occurred!
next(err) // 注意要这么写,next()进入不到下一个异常处理中间件
});
// error middleware two
app.use(function onerror(err, req, res, next) {
// an error occurred!
});
中间件处理函数中的next指代的又是什么?
指代的是栈中的下一个中间件。
proto.handle = function handle(req, res, out) {
var index = 0;
var stack = this.stack;
// ...
function next(err) {
// next callback
var layer = stack[index++];
// call the layer handle
call(layer.handle, route, err, req, res, next);
}
next();
};
通过上面代码可以看出,每次调用next()函数,会执行index++,layer为middleware stack中的下一个中间件。
其中layer.handle来自于this.stack.push({ route: path, handle: handle });。
期待和大家交流,共同进步,欢迎大家加入我创建的与前端开发密切相关的技术讨论小组:
微信公众号: 大大大前端 / excellent_developers
Github博客: 趁你还年轻233的个人博客
SegmentFault专栏:趁你还年轻,做个优秀的前端工程师
努力成为优秀前端工程师!
猜你喜欢
- 2024-10-22 调用 Express API时出现奇怪的CORS错误怎么办?
- 2024-10-22 详解如何从零开始搭建Express+Vue开发环境
- 2024-10-22 从零开始学习nodejs+express--交互环境
- 2024-10-22 express开发(一)简介与搭建(express创建项目)
- 2024-10-22 蓝易云 - centos系统直接部署express教程。
- 2024-10-22 Node + Express + Mysql: Todo List项目让你成全栈
- 2024-10-22 我为 Express 开了外挂(cad中的express怎么显示为中文)
- 2024-10-22 七爪源码:让我们 Dockerize 一个 Node.js Express 应用程序
- 2024-10-22 Node实战篇:Express--jade模板引擎(七)
- 2024-10-22 深入全面讲解Express的Cookies:原理解析与代码示例
你 发表评论:
欢迎- 03-19基于layui+springcloud的企业级微服务框架
- 03-19开箱即用的前端开发模板,扩展Layui原生UI样式,集成第三方组件
- 03-19SpringMVC +Spring +Mybatis + Layui通用后台管理系统OneManageV2.1
- 03-19SpringBoot+LayUI后台管理系统开发脚手架
- 03-19layui下拉菜单form.render局部刷新方法亲测有效
- 03-19Layui 遇到的坑(记录贴)(layui chm)
- 03-19基于ASP.NET MVC + Layui的通用后台开发框架
- 03-19LayUi自定义模块的定义与使用(layui自定义表格)
- 最近发表
-
- 基于layui+springcloud的企业级微服务框架
- 开箱即用的前端开发模板,扩展Layui原生UI样式,集成第三方组件
- SpringMVC +Spring +Mybatis + Layui通用后台管理系统OneManageV2.1
- SpringBoot+LayUI后台管理系统开发脚手架
- layui下拉菜单form.render局部刷新方法亲测有效
- Layui 遇到的坑(记录贴)(layui chm)
- 基于ASP.NET MVC + Layui的通用后台开发框架
- LayUi自定义模块的定义与使用(layui自定义表格)
- Layui 2.9.11正式发布(layui2.6)
- Layui 2.9.13正式发布(layui2.6)
- 标签列表
-
- jdk (81)
- putty (66)
- rufus (78)
- 内网穿透 (89)
- okhttp (70)
- powertoys (74)
- windowsterminal (81)
- netcat (65)
- ghostscript (65)
- veracrypt (65)
- asp.netcore (70)
- wrk (67)
- aspose.words (80)
- itk (80)
- ajaxfileupload.js (66)
- sqlhelper (67)
- express.js (67)
- phpmailer (67)
- xjar (70)
- redisclient (78)
- wakeonlan (66)
- tinygo (85)
- startbbs (72)
- webftp (82)
- vsvim (79)
本文暂时没有评论,来添加一个吧(●'◡'●)