sofish / learn-js

老婆想学 js 这件事就是一个政治任务
142 stars 9 forks source link

第五天:ES2015 Generator #7

Open sofish opened 8 years ago

sofish commented 8 years ago

4 篇关于 Generator 的文章,从入门到放弃(CSP),里面有几个重要的点:

1. 使用 yieldreturn 导致 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 就可以了。