koa-compose 类库学习
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 类库学习的更多相关文章
- 不学就吃亏的underscorejs类库学习示例 ——(集合篇)
underscorejs是一个很不错的类库,我的很多项目都引用了这个类库,的确可以带来很多方便. 记得我当初学的时候,看underscorejs的api是看的一知半解的,甚至不明白api里的conte ...
- 新一代web框架Koa源码学习
此文已由作者张佃鹏授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Koa 就是一种简单好用的 Web 框架.它的特点是优雅.简洁.表达力强.自由度高.本身代码只有1000多行 ...
- Guava:好用的java类库 学习小记
基础功能 google guava中定义的String操作 在google guava中为字符串操作提供了很大的便利,有老牌的判断字符串是否为空字符串或者为null,用指定字符填充字符串,以及拆分合并 ...
- 【开源类库学习】MBProgressHUD(提示框)
新博客: http://www.liuchendi.com MBProgressHUD是一个开源类库,实现了各种样式的提示框, 下载地址:https://github.com/jdg/MBProgre ...
- Java之基本类库学习
JAVA基本类库: (一),输入相关 main(String[] args):设置输入参数 输入类:Scanner:Scanner sc=new Scanner(System.in); (二),系统相 ...
- JavaFX 学习笔记——jfoenix类库学习——raised风格按钮创建
创建按钮 JFXButton jfxb = new JFXButton("hello"); jfxb.getStyleClass().add("button-raised ...
- 吴裕雄--天生自然java开发常用类库学习笔记:定时调度
// 完成具体的任务操作 import java.util.TimerTask ; import java.util.Date ; import java.text.SimpleDateFormat ...
- 吴裕雄--天生自然java开发常用类库学习笔记:正则表达式
public class RegexDemo01{ public static void main(String args[]){ String str = "1234567890" ...
- 吴裕雄--天生自然java开发常用类库学习笔记:观察者设计模式
import java.util.* ; class House extends Observable{ // 表示房子可以被观察 private float price ;// 价钱 public ...
随机推荐
- [转帖]HBase详解(很全面)
HBase详解(很全面) very long story 简单看了一遍 很多不明白的地方.. 2018-06-08 16:12:32 卢子墨 阅读数 34857更多 分类专栏: HBase [转自 ...
- 多线程(7)— JDK对锁优化的努力
JDK内部的“锁”优化策略 1. 锁偏向 锁偏向是针对加锁操作的优化手段,核心思想是:如果一个线程获得了锁,那么锁就进入偏向模式,当这个线程再次请求锁时,无须再做任何同步操作,这样就节省了大量有关锁申 ...
- 批处理cmd开启,关闭防火墙
管理员启动dos窗口 开启防火墙: netsh advfirewall set allprofiles state on 关闭防火墙: netsh advfirewall set allprofile ...
- FZU2018级算法第三次作业 3.16 station
题目大意: 给出1-n共n个数的入栈顺序,可以随时出栈,求出栈的最大字典序. 输入示例 输出示例 51 2 3 4 5 5 4 3 2 1 54 2 5 3 1 5 3 2 4 1 题目分析: 假设目 ...
- 使用脚本将AspNetCore发布到IIS上
首先你必须要了解的是,没有脚本的情况下,如何把AspNetCore的应用发布到IIS上. 大致分为这些步骤: 安装MS C++ 2015 x86&x64 安装正确版本的.NET Core Ru ...
- AtomicIntegerFieldUpdater和AtomicInteger
为什么有了AtomicInteger还需要AtomicIntegerFieldUpdater? 当需要进行原子限定的属性所属的类会被创建大量的实例对象, 如果用AtomicInteger, 每个实例里 ...
- dB分贝计算
1. 定义 dB-表征相对值的大小的单位,即两个电.声功率之比或者电流.电压.音量之比,是一种测相对大小的单位. 1.1 电.声功率之比——10lg(x/y) x.y分别表示两个欲比较的功率值. 例如 ...
- DO、VO、DTO 区别
DTO:数据传输对象,主要用于外部接口参数传递封装,接口与接口进行传递使用. VO:视图对象,主要用于给前端返回页面参数使用. DO:数据对象,主要用于数据库层传递. DTO转DO:接口接收参数将参数 ...
- 如何封装属于自己的WPF控件库
在网上找了一下,发现这方面的资料并不多.做传统桌面的本来就不多了吧,更别说WPF了.我可能也要另寻出路了,不过我还是觉得做桌面挺有意思的. 言归正传 首先,新建一个WPF自定义控件库项目 这里我们封 ...
- linux 基础指令
df -h 查看磁盘空间 root@ubuntu:/etc# df -h Filesystem Size Used Avail Use% Mounted on udev 970M 0 970M 0% ...