koa-中间件流程控制
koa中间件执行流程
koa中间件的的执行顺序是洋葱模型,外层逐步向内,执行到最中间再逐步向外扩展,实现这个顺序的模型需要依赖于generator函数,它可以暂停执行将控制权交出,等到执行next再得到执行权继续执行,我们需要做的就是将generator串联起来,将后面的generator函数跟在上一层函数的yield语句之后,可以看作后面的函数是next的参数,这样我们就形成了一个串联,它的执行顺序就是我们前面所提到的洋葱模型。
koa-compose
在koa中,实现上面所说的串联函数就是利用了compose,下面是compose的大概实现(在koa中叫koa-compose):
function compose (middlewares) {
return function (next) {
var i = middlewears.length;
var next = function* () {}();
while (i--) {
next = middlewares[i].call(this, next);
<!--这一点不太好理解:首先这是个递减的过程,我们会先取到最后的一个函数
然后,next函数其实是起到一个中介的作用,将next传入后又重新更新了next
也就是在下一此的运行中next函数是带有刚刚那个最内层的函数的(最后一个)
于是再进行操作,是一个递归传入的过程,可以看这篇文章:https://cnodejs.org/topic/5723360e35af8a704195f5d5
-->
}
return next;
}
}
在koa的源码中有这样的代码:
var fn = this.experimntal
? compose_es7(this.middleware)
: co.wrap(compose(this.middleware));
我们添加中间件的时候使用app.use方法,其实这个方法只是把中间件push到一个数组,很明显,所有的中间件在数组中,那么它们之间是没有联系的,所以我们会看到上面的代码,将所有的中间件都传入了我们所说的compose中。经过compose转换的代码是下面这样
//达到了洋葱模型的效果
function *() {
yield *g1(g2(g3()))
}
co模块
上面我们看到通过使用koa-compose将中间件联系在一起(串联),可是在koa中需要调用next()方法才可以驱动函数向下执行。这时候就需要用到co模块。它可以帮我们自动管理generator的next,并根据调用返回value做出不同的响应;如果遇到另外一个generator,co会继续调用自己,这就是我们为什么需要co。
简单实现原理:
function run (gen) {
var g;
if (typeof gen.next === 'function') {
g = gen;
} else {
g = gen();
}
function next () {
var tmp = g.next();
if (tmp.done) {
return;
} else if (typeof g.next === 'function') {
run(tmp.value); // 将下一步传入run函数当中
next();
}
}
next();
}
通过递归的方式(判断是否执行结束),来驱动generator的执行。
关于co模块的补充(es6)
- co会返回一个Promise对象,因此我们可以使用then方法添加回调函数
- co真正的源码做了什么
- 检查当前代码是否为Generator函数的最后一步,如果是就返回
- 确保每一步返回的结果都是promise对象
- 使用then方法为返回值加上回调函数,然后通过onFulfilled函数再次调用next函数
- 在参数不符合要求的情况下将promise状态改为Rejected从而终止模块。
ps:理解有限,如果有误请指出!
koa-中间件流程控制的更多相关文章
- 深入探析koa之中间件流程控制篇
koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...
- 使用yield进行异步流程控制
现状 目前我们对异步回调的解决方案有这么几种:回调,deferred/promise和事件触发.回调的方式自不必说,需要硬编码调用,而且有可能会出现复杂的嵌套关系,造成"回调黑洞" ...
- node核心:异步流程控制
Node.js的异步是整个学习Node.js过程中重中之重. 1)异步流程控制学习重点 2)Api写法:Error-first Callback 和 EventEmitter 3)中流砥柱:Promi ...
- node基础13:异步流程控制
1.流程控制 因为在node中大部分的api都是异步的,比如说读取文件,如果采用回调函数的形式,很容易造成地狱回调,代码非常不容易进行维护. 因此,为了解决这个问题,有大神写了async这个中间件.极 ...
- koa 中间件
什么是 Koa 的中间件 通俗的讲:中间件就是匹配路由之前或者匹配路由完成做的一系列的操作,我们就可以 把它叫做中间件. 在express中间件(Middleware)是一个函数,它可以访问请求对象( ...
- 在NodeJS中使用流程控制工具Async
本文介绍一款流程控制工具async,在编写接口或者编写测试用例的过程中总是会用到它. 由于nodejs是异步编程模型,有一些在同步编程中很容易做到的事情,现在却变得很麻烦.Async的流程控制就是为了 ...
- Koa - 中间件(理解中间件、实现一个验证token中间件)
前言 Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的. 当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件.当在下游没有更多的中间件执行后 ...
- Koa中间件(middleware)级联原理
前言 上次看到了koa-compose的代码,今天来说一下koa中间件的级联以及工作原理. 中间件工作原理 初始化koa实例后,我们会用use方法来加载中间件(middleware),会有一个数组来存 ...
- Koa 中间件的执行
Node.js 中请求的处理 讨论 Koa 中间件前,先看原生 Node.js 中是如何创建 server 和处理请求的. node_server.js const http = require(&q ...
随机推荐
- MVC和三层架构
从最开始写程序到现在,一路上听到架构这个词已经无数次了,在工作和圈子里也不停听到大家在讨论它,但是很多时候发现不少人对这个概念的理解都是很模糊的,无意间在知道上看到一个朋友的回答,感觉很不错,特转帖到 ...
- Linux配置JDK
在etc/profile文件下添加 export JAVA_HOME=/root/Desktop/jdk1.7.0_79 export CLASSPATH=/root/Desktop/jdk1.7.0 ...
- JavaScript代码规范和性能整理
性能 Js在性能方面有多要注意的地方: 避免全局查找 Js性能优化最重要的就是注意全局查找,因为作用域的查找是先找局部作用域在没有找到之后在去上一级作用域查找直到全局作用域,所以全局作用域查找的性能消 ...
- Python 3中字符串可以被改变吗?
Python 3中字符串可以被改变吗? 字符串有改变这个方法的:replace,比如: a = 'lkjhgfdsa' a.replace(') '123kjhgfdsa' #返回结果 从上面这个例子 ...
- C++:基础篇-32位和64位系统区别及字节数
今儿面试了一个刚刚毕业的,但是不知道一个int.long.double这几个都是多少位,我给你们总结一下哈: 常用数据类型对应字节数 可用如sizeof(char),sizeof(char*)等得出 ...
- Codeblocks快捷键
Codeblocks快捷键: Ctrl+Shift+Enter:复制控制台exe内容 Ctrl+Z:撤销 Ctrl+F:查找 Ctrl+R:查找替换功能 Ctrl+Shift+C:加注释 C ...
- 转:js中cookie的使用详细分析
cookie机制将信息存储于用户硬盘,因此可以作为全局变量,这是它最大的一个优点.它可以用于以下几种场合. (1)保存用户登录状态.例如将用户id存储于一个cookie内,这样当用户下次访问该页面时就 ...
- 算法模板——Dinic最小费用最大流
实现功能:输入M,N,S,T:接下来M行输入M条弧的信息(包括起点,终点,流量,单位费用):实现功能是求出以S为源点,T为汇点的网络最大流的最小费用 其实相当的像Dinic最大流呐= = 还是spfa ...
- Servlet中的过滤器Filter详解
加载执行顺序 context-param->listener->filter->servlet web.xml中元素执行的顺序listener->filter->stru ...
- 属性property和字段的区别
在类中定义的一个成员变量叫字段,要把这个成员变量变成一个属性必须加上getter和setter方法