介绍

koa-compose是koa用到的类库,用于koa中间件合并执行,compose是将多个函数合并成一个函数(eg: a() + b() +c()=> c(b(c()))),主要使用Promise/Async、递归调用实现。整个代码包括注释不到50行,非常精巧。

安装

npm install koa-compose

用法

compose([fun a{}, fun b{}, fun c{}, …])

例子

const compose=require('koa-compose')async function test(){const midFuns = []midFuns.push(async (context, next) => {console.log(1)await next()console.log(6)})midFuns.push(async (context, next) => {console.log(2)await next()console.log(5)})midFuns.push(async (context, next) => {console.log(3)await next()console.log(4)})console.log(midFuns)await compose(midFuns)({})
}
test()

next 表示调用下一个midFun,打印结果如下:

1
2
3
4
5
6

源码

'use strict'/*** Expose compositor.*/module.exports = compose/*** Compose `middleware` returning* a fully valid middleware comprised* of all those which are passed.** @param {Array} middleware* @return {Function}* @api public*/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 = -1return dispatch(0)function dispatch (i) {if (i <= index) return Promise.reject(new Error('next() called multiple times'))index = ilet fn = middleware[i]if (i === middleware.length) fn = nextif (!fn) return Promise.resolve()try {return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));} catch (err) {return Promise.reject(err)}}}
}

它返回的是一个已经合并好的函数,根据传入的函数递归调用dispatch。

  1. 首先调用dispatch(0),if (i <= index) 也就是 0<=-1不成立,继续往下走,这里主要避免在一个中间件内多次调用next
  2. 继续下一步 index = i,此时index=0了
  3. let fn = middleware[i] 获取到第一个中间件fn
  4. if (i === middleware.length) fn = next 这里的next为undefined
  5. 接下来就是最最核心的代码了,这里调用fn(也就是我们的中间件函数),并传入了两个参数一个是原来的context,一个是dispatch函数(递归调用,参数i值加1)
  return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));

dispatch.bind(null, i + 1) 返回一个新的dispatch函数,下面一个小例子,展示bind的作用

function multiply (x, y, z) {return x * y * z;
}
var double = multiply.bind(null, 2);
//Outputs: 24
console.log(double(3, 4));

我们将前面的例子代码大致转换一下,看看最后是啥样

Promise.resolve(function(context){ //第一个中间件console.log(1)await Promise.resolve(function(context){ //第二个中间件 => await next()console.log(2)await Promise(function(context){ //第三个中间件 => await next()console.log(3)// await next() 最后一个next ,不会再调用其他中间件 直接Promise.resolve()console.log(4)}());console.log(5)}())console.log(6)
}());

koa之koa-compose相关推荐

  1. koa compose源码阅读

    众所周知,在函数式编程中,compose是将多个函数合并成一个函数(形如: g() + h() => g(h())),koa-compose则是将 koa/koa-router 各个中间件合并执 ...

  2. 【koa系列】koa洋葱模型及其compose原理解析

    什么是洋葱模型 先来看一个 demo const Koa = require('koa'); const app = new Koa();// 中间件1 app.use((ctx, next) =&g ...

  3. koa源码阅读之koa-compose/application.js

    koa源码阅读之koa-compose/application.js koa-Compose 为了理解方便特地把注释也粘进来 //这英语.我也来翻译一波 //大概就是把所有的中间件组合返回一个完整大块 ...

  4. koa 接口返回数据_一文搞定 Koa 中间件实现原理

    Koa是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 通过利用 async 函数, Koa ...

  5. 第四代Express框架koa简介

    文章目录 简介 koa和express koa使用介绍 中间件的级联关系 koa的构造函数 启动http server 自定义中间件 异常处理 简介 熟悉Spring MVC的朋友应该都清楚Sprin ...

  6. 洋葱模型php,理解Koa洋葱模型

    中间件特性 | | | middleware 1 | | | | +-----------------------------------------------------------+ | | | ...

  7. Koa 中间件的执行

    Node.js 中请求的处理 讨论 Koa 中间件前,先看原生 Node.js 中是如何创建 server 和处理请求的. node_server.js const http = require(&q ...

  8. nodejs express use 传值_再也不怕面试官问你express和koa的区别了

    前言 用了那么多年的express.js,终于有时间来深入学习express,然后顺便再和koa2的实现方式对比一下. 老实说,还没看express.js源码之前,一直觉得express.js还是很不 ...

  9. 一步步实现koa核心代码

    导语:实现简单的koa核心代码,便于理解koa原理.顺便学习koa代码的那些骚操作 简单分析koa 创建一个 http 服务,只绑一个中间件.创建 index.js /** index.js */ c ...

  10. Koa在实际的业务场景中,路由如何做分割?【文末留言送书】

    大家好,我是若川.文末留言送书,具体规则文末说明.另外为了鼓励大家多写源码共读笔记,我会在写了5次及以上笔记的作者群里也抽奖送这本书.以后也会有更多福利倾斜. 导读:Koa是一个Node框架,在Nod ...

最新文章

  1. 西湖大学最年轻博导来了丨93年出生的他,想创造属于中国的“追光”纪录
  2. Boosting GDBT
  3. 剑指Offer 64 求1+2+...+n
  4. 【从 0 开始机器学习】逻辑回归识别手写字符!
  5. 5、利用控件TVCLZip和TIdFTP压缩文件并上传到FTP的线程单元pas 改进版
  6. 永磁同步电机学习(一)
  7. 客户需求分析工具-$APPEALS
  8. 固态硬盘(SSD)——NAND闪存芯片(颗粒)QLC、SLC、MLC、TLC
  9. MATLAB机器人工具箱2-机器人模型建立
  10. 【K8S】K8s部署Metrics-Server服务
  11. Android 状态栏常规操作(状态栏显示,状态栏颜色,沉浸式状态栏)
  12. 检测站营销系列文章:机动车检测站如何做精益营销?
  13. 《三国演义》十大不义之人
  14. 有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡是报到3的人退出圈子,问最后留下来的是原来的第几位(指针方法处理)。——C语言
  15. 小型音乐播放器插件APlayer.js的简单使用例子 1
  16. 【linux系统安装jdk11】
  17. 为自动驾驶carla配置车流量
  18. Lodop常用属性和方法字典(转)
  19. java必备十大技术网站
  20. case when和COALESCE

热门文章

  1. 国际短信群发的问题与优势
  2. 分布式游戏服务器全服匹配玩法设计
  3. JAVA不使用中间变量,实现两个数的交换
  4. Java入门第一课 初始概念和框架
  5. C++typename的由来和用法
  6. 在Qt中用QAxObject来操作Excel
  7. 自建小米插座服务器,暴力拆解小米智能插座并修复
  8. 快速辨别水货手机的方法
  9. chatgpt在银行领域的应用
  10. 2021-2027全球与中国宠物托管市场现状及未来发展趋势