nodejs generator 介绍

generator是什么

  1. yield关键字可以让当前函数暂停执行并保存现场,并跳出到调用此函数的代码处继续执行。
  2. 可以利用函数执行时的返回句柄的next方法回到之前暂停处继续执行
  3. next执行的返回值的value即是yield关键字后面部分的表达式结果
  4. 下一个next的唯一参数值可以作为yield的整体返回值,并赋值给a变量

    语句出处链接
看个例子:
四个名为Ai的generator函数
 function *A1(x) {
    let y = yield x;
    return y
}

function *A2(x) {  
    let y = (yield) * x;
    return y
}

function *A3(x) {  
    let y = x * (yield);
    return y
}

function *A4(x) {  
    let y = x yield; 
    return y;
}
 ```

 用下面的代码,同一跑一下,分别考虑一下出现的两次res结果是什么
 ```
let it = A(6);  
let res = it.next();  
res = it.next(7);  
  1. A1函数,6传进去,是实参数x的值,第一次next到达yield,把yield右侧表达式的值带出去了, 所以第一次res的结果是 {value : 6, done : false}

    第二次next(7),generator把7带到了yield的位置,那么y就变成了7,通过return y,把值返回给了res,所以第二次res的结果是 {value : 7, done : true}
  2. A2函数,x还是等于6,第一次yield右侧并不是一个表达式或对象,所以第一次res是 {value : undefined, done : false} 第二次next(7),generator把7带到了yield的位置,那么相当于

    let y = (yield) * x <---------------> let y = 7 * x <-----------> let y = 7 * 6

    最后return 结果就是 42

  3. 同上结果,分析雷同

  4. 会直接抛出错误
co简洁代码核心原理

来实现一个简单的co

//封装成一个promise,倒计时打印当时时间
function sleep(time) {  
    return new Promise( (resolve, reject) => {
        setTimeout( ()=> {
            resolve(new Date)
        }, time)
    }) 
}

//generator函数
function *delay() {  
    let curTime = null;

    curTime = yield sleep(1000);
    console.log(curTime);

    curTime = yield sleep(1000);
    console.log(curTime);

    curTime = yield sleep(2000);
    console.log(curTime);
}

function co(gen) {  
    let it = gen();
    next();
   //递归
    function next(data) {
       let ret = it.next(data);
       if(ret.done) return ;
       ret.value.then( (data) => {
           next(data);
       });
    }
}
co(delay)  

来看一下,delay里面的第一个sleep执行流程

1. 首先co函数执行,generator函数delay传入,形参为gen,it拿到句柄。next函数执行,参数data实际未传入任何值,为undefined

2. 第一个it.next(data),会让delay运行完第一个sleep,sleep返回了一个promise。当然,promise的构造函数的参数是一个匿名函数,它会在返回promise之前执行。也就是说先执行了setTimeout注册函数,然后执行return。这个promise就被赋值给了ret.value。

3. ret.value.then就是把then里面的函数,封装成新的promise对象(bridge promise),注册到原本promise的resolve函数数组里面

4. 后面正常运行,直到setTimeout时间超时,其匿名函数执行,这时候resolve执行。resolve执行,就把new Date传给了ret.value.then的参数(匿名函数)的参数(data)

5. 由于递归的原因,该new Date就成了next(data)里面的data,通过it.next(data)迭代器返回给了delay第一个curTime

未经同意,禁止转载

本文地址 http://blog.hacking.pub/2016/11/03/nodejs-generator-jie-shao/