koa中的yield(1)
背景介绍:
- yield 是es6新出的语法配合Generator一起使用的
- co是大神Tj写的一套操作一步流程的模块
先看看yield的定义:
由于Generator函数返回的遍历器对象只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志
yield的基本用法就不举例了,说说看有co和没有co的区别吧。举个例子:
function * test() {
yield 1
yield 2
}
function * test2() {
yield 3
yield test()
yield 4
}
var b = test2()
b.next() // {value: 3, done: false}
b.next() // Object {value: test, done: false}
b.next() // Object {value: 4, done: false}
此时并没有执行test中的代码,如果想执行test中的方法你可以这样
var b = test2()
b.next() // {value: 3, done: false}
var bb = b.next().value // Object {value: test, done: false}
bb.next() //bject {value: 1, done: false}
还有一种方法就是:
function * test() {
yield 1
yield 2
}
function * test2() {
yield 3
yield* test()
yield 4
}
var b = test2()
undefined
b.next() //Object {value: 3, done: false}
b.next() //Object {value: 1, done: false}
b.next() //Object {value: 2, done: false}
b.next() //Object {value: 4, done: false}
而在koa中,你可以直接这么写
function * test2() {
yield 3
yield* test()
yield 4
}
得到的结果和上面是一样的,这主要是因为koa内部的处理。(后续看一下源码可能会再解释这个问题)
这样看起来是不是已经很好了呢?但是这样有一个问题就是如果test中要执行异步操作,test2不会等到异步操作执行完在执行 yield 4
。
如果要真的解决异步的问题就需要co的帮助了,具体代码如下:
function *asyncFunction() {
return new Promise((resolve, reject)=> {
setTimeout(resolve, 2000, '2000')
})
}
function *async5000() {
return new Promise((resolve, reject)=> {
setTimeout(resolve, 5000, '5000')
})
}
function *test() {
var a = yield async5000()
var b = yield asyncFunction()
console.log(a)
console.log(b)
yield 2
}
co(test)
// 5000
// 2000
co中需要传递一个promise对象或者thunk函数,然后co就会自动调用next函数,co的原理(并不是源码,本段引自阮一峰的es6入门)入:
function run(gen){
var g = gen();
function next(data){
var result = g.next(data);
if (result.done) return result.value;
result.value.then(function(data){
next(data);
});
}
next();
}
run(gen);
就是循环调用next函数,从而达到我们预想的效果。