异步迭代生成器

1,023 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

大家好!我是前端爬楼工程师🚹,一个野生程序员。好奇新技术,仰慕牛大佬。如果喜欢我的文章,可以关注➕点赞,为我注入能量,与我一同成长吧~

处理异步请求

以前我们的异步代码是通过回调函数来解决的。代码如下:

function foo(x , y , cb){
    ajax(.., cb)
}
foo(11, 31, function(err, text){
    if(err){
        console.error(err)
    }else{
        console.log(text)
    }
})

现在我们通过生成器来改写这个异步代码

function foo(x, y){
    ajax(.., function (err, text){
        if(err){
            it.throw(err)
        }else{
            it.next(text)
        }
    })
}
function *main(){
   try{
       var text = yield foo(11,31)
       console.log(text)
   }catch(err){
       console.error(err)
   }
}
var it = main()
it.next() // 启动

随着it.next() 启动, 遇到yield本身暂停的代码执行起来,foo开始调用,此时yield等待接收返回值,如果it.next(text)传入text. yield接收到返回值text, 赋值给text变量,最后打印出来。如果抛的异常it.throw(err),最后被catch接收打印错误。

所以生成器内部完全可以运行异步代码,而且可以同步错误处理。

错误处理

上面是外接将错误抛入生成器中,下面看看生成器向外抛出异常的情况

function *main(){
    var s = yield "HELLO"
    yield s.toLowerCase()
}
var it = main()
it.next().value // HELLO yield传出HELLO
it.next() // TypeError next()传入undefined

第二个it.next()传入undefined,第一个yield返回值是undefined,赋值给s, 执行s.toLowerCase()报错。

如果我们第二个it.next("HELLO"),那么yield返回给我们的是{value:'hello', done:false}

生成器和Promise

function foo (){
    return request(..)
}
function *main(){
    try{
        var res = yield foo()
        console.log(res)
    }catch(er){
        console.error(er)
    }
}
var it = main()
var p = it.next().value
p.then(res=>{
    it.next(res)
}, err=> {
    it.throw(err)
})
ES7的async await替代

生成器和Promise结合就是async和await

function foo (){
    return request(..)
}
async function main(){
    try{
       var res = await yield foo()
        console.log(res)
    }catch(er){
        console.error(er)
    }
}
main()

async await 比生成器更加简单的实现了异步编程的方式。

到此异步迭代生成器就结束了。