ES6(Generator)

基本定義

Generator是一個迭代器生成函數,其返回值是一個迭代器(Iterator),可用于異步調用。

function* tell() {
    console.log('執行a處理');
    yield 'a';

    console.log('執行b處理');
    yield 'b';

    console.log('執行c處理');
    return 'c';
}

let k = tell();

// 執行next()的時候,會運行到第一個yield為止
console.log(k.next());  // 執行a處理
                        // {value: "a", done: false}

// 執行next()的時候,會運行到第二個yield為止
console.log(k.next());  // 執行b處理
                        // {value: "b", done: false}

// 執行next()的時候,會運行到第三個yield為止
console.log(k.next());  // 執行c處理
                        // {value: "c", done: true}

console.log(k.next());  // {value: undefined, done: true}

常用場景

比如某個事物只有三種狀態(狀態A,狀態B,狀態C),而這三種狀態的變化是 狀態A => 狀態B => 狀態C => 狀態A ,這就是狀態機。Generator特別適用于處理這種狀態機。

// A,B,C三種狀態循環
function* state(){
    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}

使用案例

案例1:長輪詢
// 定義一個generator函數,其返回值是一個promise
let ajax = function* () {
    yield new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({
                code: 0
            })
        }, 1000);
    })
}

// 定義一個輪詢函數,當輪詢結果的code!=0時,1秒之后開始下一次輪詢
let pull = function () {
    let generator = ajax();
    let step = generator.next();
    step.value.then((v) => {
        if (v.code != 0) {
            setTimeout(() => {
                console.log('wait');
                pull();
            }, 1000);
        } else {
            console.log(v);
        }
    })
}

pull(); // 執行輪詢
案例2:抽獎
// 抽獎處理
let draw = function (count) {
    // 此處省略具體的抽獎邏輯
    console.log(`剩余${count}次`);
}

// 根據剩余次數判斷是否執行抽獎處理
let residue = function* (count) {
    while (count > 0) {
        count--;
        yield draw(count);
    }
}

// 初始化抽獎次數為5次
let star = residue(5);

// 創建抽獎按鈕
let btn = document.createElement('button');
btn.id = 'start';
btn.textContent = '抽獎';
document.body.appendChild(btn);

// 綁定抽獎事件
document.getElementById('start').addEventListener('click', () => {
    star.next();
}, false)

補充:async

  • async 函數就是 Generator 函數的語法糖。

async 函數的含義和用法

// 異步編程

function timeout(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, 1000);
    })
}

async function asyncPrint(value, ms) {
    await timeout(ms).then(() => {
        console.log('我是異步處理');
    });
    console.log(value);
}

asyncPrint('hello world', 1000);
// 執行結果:
// 1秒之后,先打印出"我是異步處理",然后打印出"hello world"
// 普通編程

function timeout(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, 1000);
    })
}

function asyncPrint(value, ms) {
    timeout(ms).then(() => {
        console.log('我是異步處理');
    });
    console.log(value);
}

asyncPrint('hello world', 1000);
// 執行結果:
// 先打印出"hello world"
// 1秒之后,打印出"我是異步處理"
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。