learn-js
learn-js copied to clipboard
第五天:ES2015 Generator
4 篇关于 Generator 的文章,从入门到放弃(CSP),里面有几个重要的点:
1. 使用 yield 和 return 导致 for...of 结果的不同
function *foo() {
yield 1;
return 2;
}
var it = foo();
console.log( it.next() ); // { value:1, done:false }
console.log( it.next() ); // { value:2, done:true }
for(let value of foo()) {
console.log(value)
}
2. next() 可以传值
function *foo() {
var x = 1 + (yield "foo");
return x;
}
var it = foo();
console.log(it.next()); // 'foo'
console.log(it.next(1)); // 2
3. 在 Generator 嵌套 Generator 的顺序是怎样的?
当前迭代器会代理嵌套 Generator 的迭代器,流程如下:*bar() 的迭代器走到 yield *foo() 的点,进入 *foo() 完成迭代,再跳出来往下执行。
function *foo() {
var z = yield 3;
var w = yield 4;
console.log( "z: " + z + ", w: " + w );
}
function *bar() {
var x = yield 1;
var y = yield 2;
yield *foo(); // `yield*` delegates iteration control to `foo()`
var v = yield 5;
console.log( "x: " + x + ", y: " + y + ", v: " + v );
}
var it = bar();
it.next(); // { value:1, done:false }
it.next( "X" ); // { value:2, done:false }
it.next( "Y" ); // { value:3, done:false }
it.next( "Z" ); // { value:4, done:false }
it.next( "W" ); // { value:5, done:false }
// z: Z, w: W
it.next( "V" ); // { value:undefined, done:true }
// x: X, y: Y, v: V
4. 知名 Node.js 库 tj/co 的实现原理
基本上就是自执行 Generator 和 Promise 结合的结果。
// run (async) a generator to completion
// Note: simplified approach: no error handling here
function runGenerator(g) {
var it = g(), ret;
// asynchronously iterate over generator
(function iterate(val){
ret = it.next( val );
if (!ret.done) {
// poor man's "is it a promise?" test
if (typeof ret.value.then === 'function') {
// wait on the promise
ret.value.then( iterate );
}
// immediate value: just send right back in
else {
// avoid synchronous recursion
setTimeout( function(){
iterate( ret.value );
}, 0 );
}
}
})();
}
function *foo() {
var z = yield 3;
console.log(z);
var w = yield 4;
console.log(w);
}
function *bar() {
var x = yield 1;
console.log(x);
var y = yield 2;
console.log(y);
yield *foo();
var v = yield 5;
console.log(v);
}
runGenerator(bar);
结:昨晚忘记更新了,这四篇写的非常好,我猜老婆也看不懂。在 async / await 出来之前,乖乖用 tj/co 就可以了。