Koa2 洋葱模型 —— compose 串联中间件的四种实现


阅读原文


前言

Koa 是当下主流 NodeJS 框架,以轻量见长,而它中间件机制与相对传统的 Express 支持了异步,所以编码时经常使用 async/await,提高了可读性,使代码变得更优雅,上一篇文章 NodeJS 进阶 —— Koa 源码分析,也对 “洋葱模型” 和实现它的 compose 进行分析,由于个人觉得 compose 的编程思想比较重要,应用广泛,所以本篇借着 “洋葱模型” 的话题,打算用四种方式来实现 compose


洋葱模型案例

如果你已经使用 Koa 对 “洋葱模型” 这个词一定不陌生,它就是 Koa 中间件的一种串行机制,并且是支持异步的,下面是一个表达 “洋葱模型” 的经典案例。

const Koa = require("koa");

const app = new Koa();

app.use(asycn (ctx, next) => {
   
    console.log(1);
    await next();
    console.log(2);
});

app.use(asycn (ctx, next) => {
   
    console.log(3);
    await next();
    console.log(4);
});

app.use(asycn (ctx, next) => {
   
    console.log(5);
    await next();
    console.log(6);
});

app.listen(3000);

// 1
// 3
// 5
// 6
// 4
// 2

上面的写法我们按照官方推荐,使用了 async/await,但如果是同步代码不使用也没有关系,这里简单的分析一下执行机制,第一个中间件函数中如果执行了 next,则下一个中间件会被执行,依次类推,就有了我们上面的结果,而在 Koa 源码中,这一功能是靠一个 compose 方法实现的,我们本文四种实现 compose 的方式中实现同步和异步,并附带对应的案例来验证。


准备工作

在真正创建 compose 方法之前应该先做些准备工作,比如创建一个 app 对象来顶替 Koa 创建出的实例对象,并添加 use 方法和管理中间件的数组 middlewares

// 文件:app.js
// 模拟 Koa 创建的实例
const app = {
   
    middlewares: []
};

// 创建 use 方法
app.use = function(fn) {
   
    app.middlewares.push(fn);
};

// app.compose.....

module.exports = app;

上面的模块中导出了 app 对象,并创建了存储中间件函数的 middlewares 和添加中间件的 use 方法,因为无论用哪种方式实现 compose 这些都是需要的,只是 compose 逻辑的不同,所以后面的代码块中会只写 compose 方法。


Koa 中 compose 的实现方式

首先介绍的是 Koa 源码中的实现方式,在 Koa 源码中其实是通过 koa-compose 中间件来实现的,我们在这里将这个模块的核心逻辑抽取出来,用我们自己的方式实现,由于重点在于分析 compose 的原理,所以 ctx 参数就被去掉了,因为我们不会使用它,重点是 next 参数。

1、同步的实现

// 文件:app.js
app.compose = function() {
   
    // 递归函数
    function dispatch(index) {
   
        // 如果所有中间件都执行完跳出
        if (index === app.middlewares

你可能感兴趣的:(NodeJS,NodeJS,Koa,源码分析,async/await)