Generator函数比普通javascript函数的前面多了一个星号 * ,它需要与关键字yield命令配合使用,可以实现暂停执行的功能,并且可以通过生成器的next()方法恢复执行。

下面通过一段简单的代码了解yield和Generator函数的执行过程。

测试代码1:

const testYield = function*() {
    let arr = [1, 2, 3];
    for (let i = 0; i < arr.length; i++) {
        console.log(`array index: ${i}`);
        yield arr[i];
    }
};

let arkTest = testYield();
//generator的next方法原则上是可以无限次调用的,所以这里我用for循环调用5次,看看输出结果
for (let i = 0; i < 5; i++) {
    let obj = arkTest.next();
    console.log(`yield return object: {value:${obj.value}, done:${obj.done}}`);
}

执行结果:


结果分析:

第1次执行next() 输出 第1和第2行结果;

第2次执行next() 输出 第3和第4行结果;

第3次执行next() 输出 第5和第6行结果;

第4次执行next() 输出 第7行结果;   此时value已经无返回值,done标记为已完成状态

第5次执行next() 输出 第2次第7行结果;表示next可以无限次调用


接下来通过一个稍微复杂的传参示例,更加深入的理解yield和generator函数的用法。

测试代码2:

const testYield2 = function*(x) {
    let a = x;
    console.log(`step1:a=${a}`);
    let b = yield(a + 1);
    console.log(`step2:a=${a},b=${b}`);
    let c = yield b;
    console.log(`step3:a=${a},b=${b},c=${c}`);
    return c;
}
//测试数据A
let arkTest2 = testYield2(5);
for (let i = 0; i < 3; i++) {
    let obj = arkTest2.next();
    console.log(`yield return object: {value:${obj.value}, done:${obj.done}}`);
}
//测试数据B
let arkTest3 = testYield2(5);
for (let i = 0; i < 3; i++) {
    let obj = arkTest3.next(i); //注意这里next 多了一个执行索引的参数传递进去
    console.log(`yield return object: {value:${obj.value}, done:${obj.done}}`);
}

测试数据A执行结果:


一开始创建testYield2的时候,传入了参数 5,

第1次执行完next(),输出第1行和第2行的结果:

  第1行结果: a=x:5 的结果是:a=5;

  第2行结果:返回的值是 yield(a+1):a:5+1=value:6

第2次执行完next(),输出第3行和第4行的结果:

  第3行结果: b=undefined;因为第2次调用next的时候,没有传入参数,所以b=next()传入的 参数为 undefined

  第4行结果:返回的值是 yield b:所以value = b 也是undefined

第3次执行完next(),输出第5行和第6行的结果:

  第5行结果: c=undefined;因为第3次调用next的时候,没有传入参数,所以c=next()传入的 参数为 undefined

  第6行结果:返回的值是 return c:所以value =c 也是undefined,done:true表示执行完毕


测试数据B执行结果:


一开始创建testYield2的时候,传入了参数 5,

第1次执行完next(0),输出第1行和第2行的结果:

  第1行结果: a=x:5 的结果是:a=5;

  第2行结果:返回的值是 yield(a+1):a:5+1=value:6

第2次执行完next(1),输出第3行和第4行的结果:

  第3行结果: b=1;因为第2次调用next的时候,传入参数1,所以b=next(1)传入的 参数为 1

  第4行结果:返回的值是 yield b:所以value = b 也是1

第3次执行完next(2),输出第5行和第6行的结果:

  第5行结果: c=2;因为第3次调用next的时候,传入参数2,所以c=next(2)传入的 参数为 2

  第6行结果:返回的值是 return c:所以value =c 也是2,done:true表示执行完毕