生成器

108 阅读2分钟

「这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

Generator 函数为异步编程提供解决方案

ES6 新引入了 Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而为异步编程提供解决方案。

Generator 函数组成

Generator 有两个区分于普通函数的部分:

  • 在 function 后面,函数名之前有个 * ;
  • 函数内部有 yield 表达式(不一定一定有)。

Generator 函数与普通函数的区别

这是两个函数,上面没有 * 的函数是普通函数,带 * 的函数是generator函数。
普通函数点击执行:
image.png
generator函数执行后没有反应,我们执行fun1_next后才显示generator函数里面的内容。
image.png

function fun(params) {
    console.log('start');
}

function* fun1() {
    //直接打印打印不出来
    console.log("异步编程!");
}

function fun1_next(params) {
    fun1().next()
}

yield是函数代码的分隔符

3个yield把代码分割成4块,我们点击执行一次fun2_next函数就会执行fun2函数中的一块代码段,依次输出1,2,3,4

image.png

image.png

image.png

image.png

function* fun2() {
    console.log(1);
    yield 'test1'
    console.log(2);
    yield 'test2'
    console.log(3);
    yield 'test3'
    console.log(4);
}
let generator2 = fun2();
function fun2_next(params) {
    generator2.next();
}

如果只有yield没有代码段

我比较好奇,如果只有yield没有需要执行代码段会输出什么样的结果,后来发现如图所示65-68行输出。

image.png
除了使用 next ,还可以使用 for... of 循环遍历 Generator 函数生产的 Iterator 对象,如图所示70行输出。

function* fun3() {
    yield 'test1'
    yield 'test2'
    yield 'test3'
}
let generator3 = fun3();
console.log("----------------");
console.log(generator3.next());
console.log(generator3.next());
console.log(generator3.next());
console.log(generator3.next());
for (let v of fun3()) {
    console.log(v);
}

来一个题目检验一下学习成果吧

代码如下

function fun5() {
    setTimeout(() => {
        console.log(5);
        v1.next();
    }, 1500)
}

function fun6() {
    setTimeout(() => {
        console.log(6);
    }, 2000)
}

function fun7() {
    setTimeout(() => {
        console.log(7);
    }, 2500)
}

function* fun8() {
    yield fun5();
    yield fun6();
    yield fun7();            
}

let v1 = fun8();
v1.next();

问题:

输出结果是什么样的?为什么?

参考

运行结果如下:
image.png
提示:fun5有v1.next();

说明

这是作者的学习收获,如果有兴趣可以看看菜鸟教程,这里有详细说明,ES6 Generator 函数。 再推荐一篇辅助理解的文章,来自微信别人公众号辰星降落发布的 js生成器之generator函数。讲的很详细,就是字太多了,我的总结仅仅做简单用法的讲解,如果想了解太过深入的,大家可以移步看看大佬的见解。