上面一章,讲了generator中是如何实现异步的,也留下了一个问题,就是如何避免回调地狱。
g.next().value.then((err, res) => {
g.next(res).value.then((err, res) => {
g.next(res).value.then((err, res) => {
g.next(res).value.then(...)
})
})
})
稍稍观察一下这段代码,我们能发现每一个then中的回调都是一样的,那么我们能不能把这个回调函数抽取出来,做成递归呐,我们只用一直递归,直到返回done为true就可以了。
function* gen() {
yield step1()
yield step2()
yield step3()
}
function callGen(fn) {
var g = fn()
function call() {
var res = g.next()
if (res.done) return;
res.value.then(call)
}
call()
}
callGen(gen)
这里的callGen就是一个generator函数的执行器,g是迭代器的索引,call是一个闭包始终能够访问到g,这样也解决了第一章迭代器可见范围的问题,这样我们就可以在代码的任何地方,方便的调用generator函数。而这也是async/await的原理。async/await是一种generator的语法糖,await就是yield,async是*号的同时,也会帮我们自动生成一个执行器,不再需要我们手动创建。需要注意的是async返回的是一个Promise对象。