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-中间件流程控制的更多相关文章

  1. 深入探析koa之中间件流程控制篇

    koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...

  2. 使用yield进行异步流程控制

    现状 目前我们对异步回调的解决方案有这么几种:回调,deferred/promise和事件触发.回调的方式自不必说,需要硬编码调用,而且有可能会出现复杂的嵌套关系,造成"回调黑洞" ...

  3. node核心:异步流程控制

    Node.js的异步是整个学习Node.js过程中重中之重. 1)异步流程控制学习重点 2)Api写法:Error-first Callback 和 EventEmitter 3)中流砥柱:Promi ...

  4. node基础13:异步流程控制

    1.流程控制 因为在node中大部分的api都是异步的,比如说读取文件,如果采用回调函数的形式,很容易造成地狱回调,代码非常不容易进行维护. 因此,为了解决这个问题,有大神写了async这个中间件.极 ...

  5. koa 中间件

    什么是 Koa 的中间件 通俗的讲:中间件就是匹配路由之前或者匹配路由完成做的一系列的操作,我们就可以 把它叫做中间件. 在express中间件(Middleware)是一个函数,它可以访问请求对象( ...

  6. 在NodeJS中使用流程控制工具Async

    本文介绍一款流程控制工具async,在编写接口或者编写测试用例的过程中总是会用到它. 由于nodejs是异步编程模型,有一些在同步编程中很容易做到的事情,现在却变得很麻烦.Async的流程控制就是为了 ...

  7. Koa - 中间件(理解中间件、实现一个验证token中间件)

    前言 Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的. 当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件.当在下游没有更多的中间件执行后 ...

  8. Koa中间件(middleware)级联原理

    前言 上次看到了koa-compose的代码,今天来说一下koa中间件的级联以及工作原理. 中间件工作原理 初始化koa实例后,我们会用use方法来加载中间件(middleware),会有一个数组来存 ...

  9. Koa 中间件的执行

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

随机推荐

  1. XML入门知识

    什么是XML? 答:指可扩展标记语言(eXtensible Markup Language),被设计用来传输和存储数据:标签没有被预定义.您需要自行定义标签:被设计为具有自我描述性. XML和HTML ...

  2. grpc-gateway:grpc对外提供http服务的解决方案

    我所在公司的项目是采用基于Restful的微服务架构,随着微服务之间的沟通越来越频繁,就希望可以做成用rpc来做内部的通讯,对外依然用Restful.于是就想到了google的grpc. 使用grpc ...

  3. 咖啡师之路:第一日一杯Espresso

    代码敲累了.产品要发布了.熬夜啊加班啊. 精神完全不在状态. 咋办--- 咋办--- 咋办---! 来一杯Espresso浓缩咖啡.各位码农,码神们的必备良品! 咖啡每天要2-3杯,不管是速溶还是现磨 ...

  4. 浅谈HTML5中的浮动问题

    浮动是我们在前端页面中经常会用到的一种布局方式.那什么是浮动呢? 首先我们先来看一下它的定义.浮动是指让元素脱离文档标准流(脱标),按照指定的方向去横向排列.浮动的取值有两个,分别是float:lef ...

  5. node c++多线程插件 第二天 c++指针

    虽然取名叫node多线程插件,但是目前还是在学习c++的情况. 今天谈一谈c++指针. c++指针就像是c#中的引用变量,例如一个Person类的实例zs{Name="张三",Ag ...

  6. ABP入门系列(14)——应用BootstrapTable表格插件

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 引言 之前的文章ABP入门系列(7)--分页实现讲解了如何进行分页展示,但其分页展示仅适用于 ...

  7. Lucas定理学习(进阶中)

    (1)Lucas定理:p为素数,则有: (2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 =  [n/p]*p+a0,m=[m/p]*p+b0其次,我们 ...

  8. linux yum下载文件的存放位置

    默认是: /var/cache/yum也可以在 /etc/yum.conf 指定cachedir=/var/cache/yum #存放目录keepcache=1 #1为保存 0为不保存metadata ...

  9. ubuntu查看安装的cuda toolkit自带的工具及其他安装文件

    原创作品,转载请注明来源:http://www.cnblogs.com/shrimp-can/p/5253672.html 1.查看工具 默认目录为:local,进入local:cd /usr/loc ...

  10. Android开发遇到手机无法弹出Toast

    今天遇到了一个很奇怪的问题,一个很简单的程序,就是点击按钮弹出一个Toast,但在手机上运行起来,却没有正常弹出Toast 第一反应就是看看是否调用了show方法,很显然,并不是这个低级问题,为了确定 ...