返回
将Express源码级实现の路由全解析(上阕)<
前端
2023-10-13 14:37:34
新手入门阅读此文需要先阅读我的前作简单版Express实现。此次我们将用代码层面的角度,剖析Express源码实现的核心功能。
从核心切入
我们从最核心也是第一个功能入手,HTTP路由 。我们知道HTTP路由的基础功能便是解析请求路径将请求分发到不同的处理器。
在Express中,当我们调用app.get('/user', (req, res, next) => {...})时,Express是怎样把对'/user'的请求与这个回调关联起来的呢?
代码层面刨析
我们可以通过阅读源码并注释辅助理解。
// 引入中间件函数,用于处理传入的回调
function wrap(handler) {
if (typeof handler !== 'function') {
throw new TypeError('handler must be a function');
}
// 闭包返回一个中间件函数,该函数调用传入的回调并处理错误
return async (req, res, next) => {
try {
await Promise.resolve(handler(req, res, next));
} catch (err) {
// 如果发生错误,则将错误传递给下一个中间件处理
next(err);
}
};
}
// 调用该方法可注册一个HTTP路由,该方法具有三个参数,第一个参数为请求路径,第二个参数为请求处理函数,第三个参数为路由参数
exports.use = function use(path, ...handlers) {
for (const handler of handlers) {
// 将每个处理程序包装为中间件函数
let layer = wrap(handler);
// 将每个路由中间件注册到堆栈中
stack.push({
path,
method: 'use', // 请求类型
regexp, // 将path转换成正则表达式以便匹配请求路径
callbacks: [layer], // 该请求处理程序列表
paramNames: [], // 路由参数名称列表
next: undefined, // 下一个路由中间件
});
}
};
当调用use()方法时,便会将一个或多个请求处理程序注册到路由中间件的堆栈中。这就是如何关联HTTP路由与请求处理程序的方式。
总结
HTTP请求是如何和请求处理器关联起来的呢?答案就是中间件。在Express中,请求处理程序被包装成中间件函数,然后被注册到一个堆栈中,这样当请求到达时,就会按照注册顺序依次执行中间件。