生成器 前端学习(ES6) 笔记

一、生成器函数声明与调用

生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数不同
是一个特殊的函数
之前异步编程是用纯回调函数来解决的
(一层套一层),例如:node fs ajax mongodb

声明方式特殊

在function 与 函数名中添加一个 * 号(位置偏左偏右靠中间都可以)

        function * geo(){
            console.log("hello generator")
        }

执行方式特殊

如果直接调用控制台将打印

    <script>
        function * geo(){
            console.log("hello generator")
        }
        let iterator = geo();
        console.log(iterator)
    </script>

控制台输出的其实是迭代器对象,里面有next方法
本质还是迭代器

借助迭代器中的next()方法执行log语句

        function * geo(){
            console.log("hello generator")
        }
        let iterator = geo();
        // console.log(iterator)
        iterator.next();

使用.next()方法

生成器可出现yield语句
yield:The yield keyword is used to pause and resume a generator function.
算是函数代码的分割符


通过next方法来控制向下执行的,而不是像之前一样一直到花括号结束
既然是迭代器就可以用for of 遍历

        function * geo(){
            // console.log("hello generator")
            //console.log(111);
            yield 1;
            //console.log(222);
            yield 2;
            //console.log(333);
            yield 3;
        }
        let iterator = geo();

        for(let v of geo()){
            console.log(v);
        }

在这里插入图片描述

二、生成器函数的参数传递

无参时,调用next方法将返回yield值

        function * gen2(){
            yield 111;
            yield 222;
            yield 333;
        }
        let iterator2 = gen2();
        console.log(iterator2.next());
        console.log(iterator2.next());
        console.log(iterator2.next());
        console.log(iterator2.next());

在这里插入图片描述

带参数,需要调用next语句才会有输出

function * gen2(arg){
            console.log(arg)
            yield 111;
            yield 222;
            yield 333;
        }
        let iterator2 = gen2('AAA');	//如只有这句,控制台将不会输出
        console.log(iterator2.next());		//调用next方法,函数输出到第一个yield

在这里插入图片描述
next方法也可以传参数,参数将作为上一个yield的返回结果
因为这个特性,将支持异步编程参数传递

function * gen2(arg){
            console.log(arg)
            let one = yield 111;
            console.log(one);
            let two = yield 222;
            console.log(two)
            let three = yield 333;
            console.log(three)
        }
        let iterator2 = gen2('我是定义处的参数');
        console.log(iterator2.next());
        console.log(iterator2.next('AAA'));
        console.log(iterator2.next());
        console.log(iterator2.next('CCC'));

第二个next(‘AAA’)的方法调用将作为第一个yield 返回结果,用let one接收
生成器函数被yield划分为4块,第36行的log(one)输出的是上一块的(即:one = yield 111;)one接收的值;
next执行到yield即停,等待下一个next调用。对应关系如图所示(3个yield将函数分为四块)
在这里插入图片描述

三、生成器函数实例1

生成器函数是异步编程的另一种解决方案
异步编程:整个js都单线程,异步单线程,很多操作都是单线程的(特别是io方面),例如:文件操作、网络操作(ajax,request)、数据库操作

实例1:1s后控制台输出 111 后 2s后输出 222 后 3s后输出333
6秒后显示效果

        setTimeout(() => {
            console.log(111);
            setTimeout(() => {
                console.log(222);
                setTimeout(() => {
                    console.log(333);

                }, 3000);
            }, 2000);
        }, 1000);

缺点:层次叠加,代码缩进,回调地狱

生成器函数在异步编程中的表现

        function one(){
            setTimeout(()=>{
                console.log(111);
                iterator.next();

            },1000)
        }
        function two(){
            setTimeout(()=>{
                console.log(222);
                iterator.next();

            },2000)
        }
        function three(){
            setTimeout(()=>{
                console.log(333);
                iterator.next();
                
            },3000)
        }

        function * gen(){
            yield one();
            yield two();
            yield three();
        }
        //调用生成器函数
        let iterator = gen();
        iterator.next();

在计时器后调用迭代器.next(箭头函数作用域是和父级的上下文绑定在一起的)即定时器为箭头函数,他的父级one()上下文绑定在一起的,为window下的iterator,所以可以在里面使用iterator.next()

用生成器函数后,缩进有止境,解决了回调地狱

四、生成器函数实例2

伪订单查询 用户数据、订单数据、商品数据的顺序

 function getUsers(){
            setTimeout(()=>{
                let data = '我是用户数据';
                iterator.next(data);    
                //这是第二次调用next,data将作为yield 的实参返回
            },1000)
        }
        function getOrders(){
            setTimeout(()=>{
                let data = '我是订单数据';
                iterator.next(data);    
            },1000)
        }
        function getGoods(){
            setTimeout(()=>{
                let data = '我是商品数据';
                iterator.next(data);    
            },1000)
        }

        function * gen(){
            let users = yield getUsers();
            console.log(users);
            let orders = yield getOrders();
            console.log(orders);
            let goods = yield getGoods();
            console.log(goods)
        }
        //调用生成器函数
        let iterator = gen();
        iterator.next();

在这里插入图片描述
总结:yield、异步编程、解决回调地狱问题

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值