es6学习笔记整理(十五)Generator生成器

基本概念

Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。
形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号,二是,函数体内部使用yield语句,定义不同的内部状态。(yield语句在英语里的意思就是“产出”)

next函数的用法
let tell = function* (){
    yield 'a';
    yield 'b';
    return 'c'
};

let k = tell();

console.log(k.next());//{value: "a", done: false}
console.log(k.next());//{value: "b", done: false}
console.log(k.next());//{value: "c", done: true}
console.log(k.next());//{value: undefined, done: true}

调用第一个next,会去执行第一个yield,调用第二个next,会去执行第二个yeild,
以此类推,函数体内部是个异步调用的过程

yield*的语法

使用genertor也可以作为遍历器的返回值

        let obj = {};
        obj[Symbol.iterator] = function* (){
            yield 1;
            yield 2;
            yield 3;
        };

        for(let value of obj){
            console.log(value);//1 2 3
        }
高级用法,状态机

generator特别适用的情况

        let state = function* (){
            while(1){
                yield 'A';
                yield 'B';
                yield 'C';
            }
        }
        let status = state();
        console.log(status.next());//{value: "A", done: false}
        console.log(status.next());//{value: "B", done: false}
        console.log(status.next());//{value: "C", done: false}
        console.log(status.next());//{value: "A", done: false}
        console.log(status.next());//{value: "B", done: false}
        console.log(status.next());//{value: "C", done: false}
        console.log(status.next());//{value: "A", done: false}

以上的例子中,无论你连续调用多少次.next(),done的值都不可能是true,会一直循环打印。
还有一种async形式的,但是浏览器需要添加兼容包才可识别,所有的功能和方法的使用都和上面的一样,结果也一样。反正先写下来,做一个提示:

let state = async function (){
    while(1){
        await 'A';
        await 'B';
        await 'C';
    }
}
let status = state();
console.log(status.next());//{value: "A", done: false}
console.log(status.next());//{value: "B", done: false}
console.log(status.next());//{value: "C", done: false}
console.log(status.next());//{value: "A", done: false}
console.log(status.next());//{value: "B", done: false}
console.log(status.next());//{value: "C", done: false}
console.log(status.next());//{value: "A", done: false}
使用实例1

有一个例子,看看实际如何运用。
以下例子中,实现前端抽奖剩余次数限制,使用generator做判断

let draw = function (count) {
    //具体业务逻辑
    console.info(`剩余${count}次`)
};

//计算剩余次数,原来使用的是全局变量,现在通过generator来进行判断
let residue = function* (count){
    while (count>0){
        count--;
        yield draw(count);
    }
};
let star = residue(5);
let btn = document.createElement('button');
btn.id = 'start';
btn.textContent = '抽奖';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click', function (){
    star.next();
},false);
使用实例2

长轮循:服务端某一个数据状态定期的变化,前端需要获取时,除了webSocket,还常轮循,由于webSocket的浏览器兼容不好,所以长轮循还是很常用的,之前的做法是使用定时器定时的发送请求,现在通过generator来实现。

let ajax = function* (){
    yield new Promise(function(resolve, reject){
        //这里应该写请求,现在使用定时器代替
        setTimeout(function (){
            resolve({code:0});
        },200);
    });
};

let pull = function (){
    let generator = ajax();
    let step = generator.next();
    step.value.then(function(d){
        if(d.code != 0){
            setTimeout(function (){
                console.log('wait');
                pull();
            },1000);
        }else{
            console.log(d);//{code: 0}
        }
    });
};
pull();

你可能感兴趣的:(es6学习笔记整理(十五)Generator生成器)