您的位置:首页 > 其它

koa中yield next的含义

2018-01-10 12:28 183 查看
先来一段代码:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  koa yield next generator