> ## Content Index
> Fetch the complete content index at: https://blog.hacking.pub/llms.txt
> Use this file to discover other available public pages before exploring further.

# nodejs generator 介绍
- URL: https://blog.hacking.pub/2016/11/03/nodejs-generator-jie-shao/
- Published: 2016-11-03T11:17:35.000Z
- Updated: 2016-11-23T06:03:12.000Z
- Author: chainhelen

#### generator是什么

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

> [语句出处链接](http://cnodejs.org/topic/542953d42ca9451e1bf3c251?ref=blog.hacking.pub)

###### 看个例子：

四个名为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函数，６传进去，是实参数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

1. 同上结果，分析雷同
2. 会直接抛出错误

###### 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/](https://blog.hacking.pub/2016/11/03/nodejs-generator-jie-shao/)