内容简介:第一篇文章中我们讲过,“在Koa中,中间件是指连贯整个 Koa 应用程序,并共享资源的独立插件”,注意两个词,“连贯”与“共享资源”,与上面的代码一一对应,“连贯”对应“next”,“共享资源对应context”。Koa 中通过 next 贯穿整个应用程序,下面分析一下 next 中做了什么。Koa 类中的构造函数中初始化了一堆数据,其中两个重要的,一个是“middleware”,另一个是“context”。(非关键代码使用…省略)
第一篇文章中我们讲过,“在Koa中,中间件是指连贯整个 Koa 应用程序,并共享资源的独立插件”,注意两个词,“连贯”与“共享资源”,与上面的代码一一对应,“连贯”对应“next”,“共享资源对应context”。
Koa 中通过 next 贯穿整个应用程序,下面分析一下 next 中做了什么。
中间件集合
Koa 类中的构造函数中初始化了一堆数据,其中两个重要的,一个是“middleware”,另一个是“context”。(非关键代码使用…省略)
constructor() {
...
this.middleware = [];
this.context = Object.create(context);
...
}
所有的中间件在一个数组存放,当我们调用“app.use”方法的时候会往数组中加入我们自定义的中间价
use(fn) {
...
this.middleware.push(fn);
return this;
}
最后通过“koa-compose”来统一触发中间件队列
callback() {
const fn = compose(this.middleware);
...
return (req, res) => {
...
fn(ctx).then(() => respond(ctx)).catch(ctx.onerror);
};
}
koa-compose
koa-compose 源码只有短短几十行,关键代码不到10行,直接贴上源码
function compose (middleware) {
if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
for (const fn of middleware) {
if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
}
/**
* @param {Object} context
* @return {Promise}
* @api public
*/
return function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch (i) {
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, function next () {
return dispatch(i + 1)
}))
} catch (err) {
return Promise.reject(err)
}
}
}
}
如果我们需要使用 Koa 的洋葱模型可以直接调用 koa-componse 来达到目的
const koaCompose = require('koa-compose');
const middleware1 = (ctx, next) => {
console.log('middleware1 >>>>>');
next();
console.log('middleware1 <<<<<');
}
const middleware2 = (ctx, next) => {
console.log('middleware2 >>>>>');
next();
console.log('middleware2 <<<<<');
}
const middleware3 = (ctx, next) => {
console.log('middleware3 >>>>>');
console.warn(ctx);
next();
console.log('middleware3 <<<<<');
}
const fn = koaCompose([middleware1, middleware2, middleware3]);
fn({ a: 'a' }, (ctx) => {
console.warn(ctx);
console.warn('The last next use do =======<');
return ctx;
}).then((ctx) => {
console.warn(ctx);
console.warn('end =====<');
});
输出:
middleware1 >>>>>
middleware2 >>>>>
middleware3 >>>>>
{ a: 'a' }
{ a: 'a' }
The last next use do =======<
middleware3 <<<<<
middleware2 <<<<<
middleware1 <<<<<
undefined
end =====<
精简 koa-componse
为了更好的分析代码,去除 koa-componse 代码中的各种非关键判断及异步处理逻辑后,代码如下
const compose = function (middlewares) {
// 返回一个函数,提供两个参数,一个是传入的上下文,另一个是所有中间件执行完毕后回调
return function(context, last) {
let idx = -1; // 初始定义当前执行中间件下标未-1,即表示当前未执行任何中间件
return dispatch(0); // 手动触发第1个中间件
function dispatch(i) {
idx = i; // 设置当前执行中间件下标
let fn = middlewares[i] || last;
try {
// 执行当前中间件的时候,给当前中间件参数中的next参数赋值为一个函数,在这个函数中执行下一个中间件
if (fn) fn(context, function() {
dispatch(i + 1); // 触发下一个中间价,并且将中间件执行下标+1
})
} catch (err) { // 所有的中间件执行完毕,执行最后回调
last(context);
}
}
}
};
执行代码:
const run = compose([middleware1, middleware2, middleware3]);
run({ a: 'a' }, () => {
console.warn('Middlewares do last =======<');
});
输出:
middleware1 >>>>> middleware2 >>>>> middleware3 >>>>> Middlewares do last =======< middleware3 <<<<< middleware2 <<<<< middleware1 <<<<<
总体思路
- 将所有中间件推送到一个数组中
- 第一个中间件首先执行
- 在第一个中间件执行前,将第一个中间件中的 next 参数设置为一个触发下一个中间件执行的函数
- 第一个中间件调用 next 函数,把执行器交给下一个中间价
- 循环往复,直最后一个中间件执行完毕
- 所有中间件执行完毕后,依次执行next外层代码
优点
- 解决多重回调地狱模式
- 统一处理上下文context挂载与传递
-
异常捕获
缺点
- 当一个项目中存在多个中间件时,对于性能会有一定影响,对于优化来说是一种考验
参考资料
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Koajs中间件之定义(三)
- Koajs中间件之定义(一)
- 自定义 Traefik2 中间件
- 在Ocelot中使用自定义的中间件(一)
- asp.net core 3.1 自定义中间件实现jwt token认证
- node.js – passport.initialize()中间件未用于快速4.10的自定义回调
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
平台革命:改变世界的商业模式
[美]杰奥夫雷G.帕克(Geoffrey G. Parker)、马歇尔W.范·埃尔斯泰恩(Marshall W. Van Alstyne)、桑基特·保罗·邱达利(Sangeet Paul Choudary) / 志鹏 / 机械工业出版社 / 2017-10 / 65.00
《平台革命》一书从网络效应、平台的体系结构、颠覆市场、平台上线、盈利模式、平台开放的标准、平台治理、平台的衡量指标、平台战略、平台监管的10个视角,清晰地为读者提供了平台模式最权威的指导。 硅谷著名投资人马克·安德森曾经说过:“软件正在吞食整个世界。”而《平台革命》进一步指出:“平台正在吞食整个世界”。以平台为导向的经济变革为社会和商业机构创造了巨大的价值,包括创造财富、增长、满足人类的需求......一起来看看 《平台革命:改变世界的商业模式》 这本书的介绍吧!