一、什么是生成器?

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

二、基本使用

<script>
    // 生成器其实就是一个特殊的函数
    // 异步编程 纯回调函数 node fs ajax mongodb
    // yield:函数代码的分隔符
    function * gen() {
    console.log(111); yield '一只没有耳朵';
    console.log(222); yield '一只没有尾部';
    console.log(333); yield '真奇怪'; console.log(444);
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log("遍历:");
//使用for of遍历
for(let v of gen()){
    console.log(v);
}
</script>

运行结果:
%title插图%num

三、案例一

生成器函数是异步编程解决方案,js是单线程的。如:文件操作 网络操作(ajax, request) 数据库操作都是异步操作的。

案例需求:1s 后控制台输出 111 ;2s后输出 222 ;3s后输出 333。

回调地狱

setTimeout(() => {
    console.log(111);
    setTimeout(() => {
        console.log(222);
        setTimeout(() => {
            console.log(333);
        }, 3000);
    }, 2000);
}, 1000);

使用生成器函数解决

使用定时器setTimeout模拟异步行为。

<script>
    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(); //向下执行进入one()
</script>

四、案例二

模拟依次获取: 用户数据 订单数据 商品数据
使用定时器setTimeout模拟异步行为。
不能直接调用对应的方法,因为只有获取到了用户数据才可以找到对应的订单,然后根据订单才可以获取商品数据。定时器都是1秒的情况系统无法获取先后顺序,需要用异步解决。

function getUsers(){
    setTimeout(()=>{
        let data = '用户数据';
        //调用 next 方法, 并且将数据传入
        iterator.next(data);
    }, 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();
    let orders = yield getOrders();
    let goods = yield getGoods();
}

//调用生成器函数
let iterator = gen();
iterator.next();

结果依次打印出:用户数据 订单数据 商品数据