es6-16 Generator

Generator是一个迭代器生成函数,其返回值是一个迭代器(Iterator),可用于异步调用。

格式演示

{
    let tell = function* () {
        yield 'a'
        yield 'b'
        return 'c'
    }
    let k = tell()

    // 通过 next() 依次执行 yield
    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}
}

Object 是没有 iterator 的, 是不能使用 for of 的, 这里使用创建 Generator 函数的方式

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

    for (let key of obj) {
        console.log(key) // 1 2 3
    }
}

generator 优势点 状态机

{
    // 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}
}

async 函数就是 Generator 函数的语法糖

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

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

    asyncPrint('hello world', 1000);
    // 执行结果:
    // 1秒之后,先打印出"我是异步处理",然后打印出"hello world"
}

抽奖次数限制示例

{
    let draw = function(count) {
        // 抽奖逻辑......
        console.info(`剩余${count}次`)
    }

    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()
    })
}

长轮询

{
    let ajax = function* () {
        yield new Promise(function(resolve, reject){
            setTimeout(function () {
                resolve({code: 0})
            }, 2000)
        })
    }

    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)
            }
        })
    }
    pull()
}
posted @ 2019-11-12 18:21  Helzeo  阅读(83)  评论(0编辑  收藏  举报