koa中yield next的含义

3 篇文章 0 订阅
3 篇文章 0 订阅

先来一段代码:

var koa = require('koa');
var app = new koa();

app.use(function *(next){
    var start = new Date;
    yield next;
    var ms = new Date - start;
    console.log('X-Response-Time', ms + 'ms');
});

// logger
app.use(function *(next){
    var start = new Date;
    yield next;
    var ms = new Date - start;
    console.log('in logger: %s %s - %s', this.method, this.url, ms+'ms');
});

// response
app.use(function *(){
    this.body = 'Hello World';
});

app.listen(2000);
console.log('listen 2000....................');

疑问:
1.代码执行结果是什么?
2. yield next 是什么意思?

答案:
1、

in logger: GET / - 2ms
X-Response-Time 4ms

2、有点长。先看看对代码执行顺序的分析

var koa = require('koa');
var app = new koa();

// x-response-time
app.use(function *(next){
  // (1) 进入路由
  var start = new Date;
  yield next;
  // (5) 再次进入 x-response-time 中间件,记录2次通过此中间件「穿越」的时间
  var ms = new Date - start;
  console.log('X-Response-Time', ms + 'ms');
  // (6) 返回 this.body
});

// logger
app.use(function *(next){
  // (2) 进入 logger 中间件
  var start = new Date;
  yield next;
  // (4) 再次进入 logger 中间件,记录2次通过此中间件「穿越」的时间
  var ms = new Date - start;
  console.log('%s %s - %s', this.method, this.url, ms);
});

// response
app.use(function *(){
  // (3) 进入 response 中间件,没有捕获到下一个符合条件的中间件,传递到 upstream
  this.body = 'Hello World';
});

app.listen(3000);

级联代码(Cascading)
Koa 中间件以一种非常传统的方式级联起来,你可能会非常熟悉这种写法。

在以往的 Node 开发中,频繁使用回调不太便于展示复杂的代码逻辑,在 Koa 中,我们可以写出真正具有表现力的中间件。与 Connect 实现中间件的方法相对比,Koa 的做法不是简单的将控制权依次移交给一个又一个的中间件直到程序结束,Koa 执行代码的方式有点像回形针,用户请求通过中间件,遇到 yield next 关键字时,会被传递到下一个符合请求的路由(downstream),在 yield next 捕获不到下一个中间件时,逆序返回继续执行代码(upstream)。

下边这个例子展现了使用这一特殊方法书写的 Hello World 范例:一开始,用户的请求通过 x-response-time 中间件和 logging 中间件,这两个中间件记录了一些请求细节,然后「穿过」 response 中间件一次,最终结束请求,返回 「Hello World」。

当程序运行到 yield next 时,代码流会暂停执行这个中间件的剩余代码,转而切换到下一个被定义的中间件执行代码,这样切换控制权的方式,被称为 downstream,当没有下一个中间件执行 downstream 的时候,代码将会逆序执行。

另外解释:

在koa里定义的middleware均为generator function(包括内置在顶端的respond),这是为了能从任意middleware中容易地切换到其它middleware里(如果你是前端程序员,可以理解为浏览器捕获事件的capture和propagation过程,如果你是python程序员,可以理解为Djangle的middleware机制,如果你是Java程序员,这种方式则是典型的切面编程)。为了实现这种横穿多个middleware的特性,koa通过把后一个generator作为参数(koa里常用next)传入前一个generator实现(#见koa-compose源码,这也是为什么前两个middleware有next参数而最后一个没有)。可以看到,在koa中yield的使用是在co,而co则是包装了generator/yield & Promise以模拟async/await,提供了一个更高层次的异步语法抽象。koa在加载且合并所有的middleware之后,传递给co执行(确切地说是在http.createServer的callback触发后执行),co以图中所示逻辑不断拆解generator function,执行yield右侧固定的几种表达式(Array,Object,generator function,Promise,thunkify function),这5种表达式最终都会转化为Promise,以达到处理异步函数的目的。co内部封装了onFulfilled和onRejected函数,当yield右侧的promise resolve之后,则会调用onFullfield函数,其包含了一条关键语句gen.next(res)#这句代码 用以给yield表达式赋值并执行下一次迭代。koa通过上文的方式「深入」->「浅出」,最终在顶层的respond middleware里send response。

出处:
1.https://github.com/guo-yu/koa-guide/blob/v2.x/README.md
2.https://www.zhihu.com/question/30258965 何洋
3.http://blog.csdn.net/qiqingjin/article/details/51221493

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值