洋葱模型 koa-compose 源码学习笔记

1,278 阅读2分钟

我正在参与掘金会员专属活动-源码共读第一期,点击参与

前言

洋葱模型大家都知道吧,其实 nodekoa 框架就是一个洋葱模型,而今天我们要学习的源码就是有关于 koa 的 — koa-composekoa 是个 nodejs 框架,使用了 async/await 来处理异步逻辑。接下来就来和大家一起学习并阅读这个源码。

koa-compose

先来介绍一下它吧,这里面 compose 是一个工具函数,koa-compose 是一个库,也可以称为是工具函数,它可以用于 koa 中间件。关于它的源码部分不多,大概就二三十行,阅读起来还是比较轻松易懂的。

源码解读

相关代码如下:

module.exports = compose
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!')
  }
  return function (context, next) {
    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, dispatch.bind(null, i + 1)))
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }
}

从代码出发,可以看到它首先做了类型的判断,middleware 必须是数组,middleware 里的元素必须是 function

然后它返回了一个接收两个参数 contextnext 的函数,又称作中间件函数。contextkoa 的上下文对象。next() 函数可以理解为如下图所示,是 dispatch.bind(null, i + 1)

image.png

return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))

我们可以从代码中看出,使用 next() 方法是将多个异步函数转为同步函数,这是一种比较常见的处理方法。

在源码的最后,我们可以看到中间件执行完后返回的是一个 Promise 对象。

总结

koa 是非常小巧的框架,它的思想就是洋葱模型,又称为中间件模型。koa-compose 巧妙的运用了 compose 的特性,结合 async/awaitnext 的等待执行,形成了我们常说的洋葱模型。

在没接触这个东西之前,我了解并使用 koa-core 以及 koa-router。如今通过这次阅读源码,又掌握了一个 koa-compose,让我对 koa 框架以及 koa-compose 有了更进一步的认识。