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