koa-compose 是koa 框架的根源的根源 ,是其实现洋葱包裹型中间件的基础

以下是koa2.X 版本所以依赖的compose 版本 ,其主要核心依赖于new Promise.resolve();遍历  middleware 中间件集合,通过递归的方式来让每个prmise按步执行

注:koa每添加一个中间件实则相 ,给koa对象的middleware 中间件数组push一个新值;

//koa 对象的use方法最核心代码
use(fn) {
this.middleware.push(fn);
return this;
}

compose核心代码 【compose其实就是一个尾递归函数 ;   递归相对低效且消耗系统资源】

Compose 是一种基于 Promise 的流程控制方式,可以通过这种方式对异步流程同步化,解决之前的嵌套回调和 Promise 链式耦合。


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
//直接执行dispatch,并且从中间件数组下标0处开始执行中间件;
return dispatch(0); /**
* dispatch 函数,属于内部核心模块
*/
function dispatch (i) { //合理性判断,如果如果参数小于等于下标就说明当前中间件被多次执行则抛出异常
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i // 对已参数为下标的当前中间件进行局部缓存
let fn = middleware[i] // 判断是否已到达中间件数组末尾,如果到达末尾则 返回不带参数的promise
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve() try {
//正常情况函数执行最终返回带有回调的promise,并且其参数就为某一个中间件
return Promise.resolve(fn(context, function next () {
return dispatch(i + 1)
}))
} catch (err) {
return Promise.reject(err)
}
}
}
}

第一次,此时第一个中间件被调用,dispatch(0),展开:

Promise.resolve(function(context, next){
//中间件一第一部分代码
await/yield next();
//中间件一第二部分代码
}());

很明显这里的next指向dispatch(1),那么就进入了第二个中间件;

第二次,此时第二个中间件被调用,dispatch(1),展开:

Promise.resolve(function(context, 中间件2){
//中间件一第一部分代码
await/yield Promise.resolve(function(context, next){
//中间件二第一部分代码
await/yield next();
//中间件二第二部分代码
}())
//中间件一第二部分代码
}());

很明显这里的next指向dispatch(2),那么就进入了第三个中间件;

第三次,此时第二个中间件被调用,dispatch(2),展开:

Promise.resolve(function(context, 中间件2){
//中间件一第一部分代码
await/yield Promise.resolve(function(context, 中间件3){
//中间件二第一部分代码
await/yield Promise(function(context){
//中间件三代码
}());
//中间件二第二部分代码
})
//中间件一第二部分代码
}());






















												

koa-compose 类库学习的更多相关文章

  1. 不学就吃亏的underscorejs类库学习示例 ——(集合篇)

    underscorejs是一个很不错的类库,我的很多项目都引用了这个类库,的确可以带来很多方便. 记得我当初学的时候,看underscorejs的api是看的一知半解的,甚至不明白api里的conte ...

  2. 新一代web框架Koa源码学习

    此文已由作者张佃鹏授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Koa 就是一种简单好用的 Web 框架.它的特点是优雅.简洁.表达力强.自由度高.本身代码只有1000多行 ...

  3. Guava:好用的java类库 学习小记

    基础功能 google guava中定义的String操作 在google guava中为字符串操作提供了很大的便利,有老牌的判断字符串是否为空字符串或者为null,用指定字符填充字符串,以及拆分合并 ...

  4. 【开源类库学习】MBProgressHUD(提示框)

    新博客: http://www.liuchendi.com MBProgressHUD是一个开源类库,实现了各种样式的提示框, 下载地址:https://github.com/jdg/MBProgre ...

  5. Java之基本类库学习

    JAVA基本类库: (一),输入相关 main(String[] args):设置输入参数 输入类:Scanner:Scanner sc=new Scanner(System.in); (二),系统相 ...

  6. JavaFX 学习笔记——jfoenix类库学习——raised风格按钮创建

    创建按钮 JFXButton jfxb = new JFXButton("hello"); jfxb.getStyleClass().add("button-raised ...

  7. 吴裕雄--天生自然java开发常用类库学习笔记:定时调度

    // 完成具体的任务操作 import java.util.TimerTask ; import java.util.Date ; import java.text.SimpleDateFormat ...

  8. 吴裕雄--天生自然java开发常用类库学习笔记:正则表达式

    public class RegexDemo01{ public static void main(String args[]){ String str = "1234567890" ...

  9. 吴裕雄--天生自然java开发常用类库学习笔记:观察者设计模式

    import java.util.* ; class House extends Observable{ // 表示房子可以被观察 private float price ;// 价钱 public ...

随机推荐

  1. Python-04-数据结构

    一.数字 整数 Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:1,100,-8080,0,等等. 计算机由于使用二进制,所以,有时候用十六进制表示 ...

  2. WUSTOJ 1308: 采药(Java)动态规划-01背包

    题目链接:

  3. 基于openfire的IM即时通讯软件开发

    openfire:http://www.igniterealtime.org/ Xmpp:http://xmpp.org/ IOS(xmppframework):https://github.com/ ...

  4. 异常:[vue/no-parsing-error] Parsing error:x-invalid-end-tag

  5. Angular Material (Components Cdk) 学习笔记 Table

    refer : https://material.angular.io/cdk/table/overview https://material.angular.io/components/table/ ...

  6. apply,call和bind的使用及区别

    1.用途 1)apply,call和bind都是 用来改变this的指向 2)apply和call会让当前函数立即执行,而bind会返回一个函数,后续需要的时候再调用执行 2.this指向问题 thi ...

  7. Git pull记住密码

    在使用https git拉取代码时,每次git pull的时候都会让输入用户名和密码 进入项目目录 命令:git config --global credential.helper store 然后会 ...

  8. Django Rest framework的限流实现流程

    目录 一 什么是throttle 二 Django REST framework是如何实现throttle的 三 Django REST framework中throttle源码流程 一 什么是thr ...

  9. print函数用法总结

    输出print函数总结: 1,字符串和数字类型 2,变量(数值,布尔,列表,字典) 3,格式化输出 格式化输出总结: (1)%:标记转换说明符的开始 (2)转换标志: - 表示左对齐:+ 表示在转换值 ...

  10. Html5知识精粹纪录

    1. HTML5文档的正文结构及新元素 正文结构: <header> <nav> <section> <aside> <footer> 深入 ...