前言
已经有了个promise用来处理异步了,官方为何又要打造一个async,await来处理异步?
通常我们发接口请求,可能需要保证一个顺序,但是各个接口耗时又不同,因此我们需要将其捋成同步,比如下面模拟下用promise解决异步
function request (num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * 10)
}, 1000)
})
}
// const res1 = request(1)
// const res2 = request(res1)
request(1).then(res1 => {
console.log(res1);
request(res1).then(res2 => {
console.log(res2);
})
})
这里的情景是,两次接口请求,第二次需要依赖第一个返回的结果,写成这么一坨,形成的链式调用感觉很不优雅
好,现在看下async,await如何解决的
async function fn() {
const res1 = await request(1) // await会把promise中的resolve值提取出来
const res2 = await request(res1)
console.log(res2);
}
fn()
我们再回顾下generator如何处理异步的,这里请求了三次
function* gen() { // generator处理异步
const num1 = yield request(1)
const num2 = yield request(num1)
const num3 = yield request(num2)
return num3
}
let g = gen()
const next1 = g.next()
next1.value.then(res1 => {
console.log(res1);
const next2 = g.next(res1)
next2.value.then(res2 => {
console.log(res2);
const next3 = g.next(res2)
next3.value.then(res3 => {
console.log(res3);
})
})
})
generator处理异步更加不美观……
async,await的打造是基于promise和generator的
generator详解:详聊es6的Generator - 掘金 (juejin.cn)
async关键字会让函数默认返回一个promise对象
如果一个函数接收的参数还是个函数体,或者返回一个函数体,那么这个函数就被称之为
高阶函数所以这些函数都是
高阶函数
async源码实现
async的核心还是generator,需要手动一直next调用,这里需要用上递归,其实co模块的源码就是下面的loop函数
function generatorToAsync(generatorFn) {
const gen = generatorFn()
return function () {
return new Promise((resolve, reject) => {
function loop (key, arg) {
let res = null
res = gen[key](arg)
const { value, done } = res
if (done) {
return resolve(value)
} else {
Promise.resolve(value).then(res => { // promise直接交给resolve得话,promise中resolve的值会传过来
loop('next', value)
})
}
}
loop('next')
})
}
}
最后
其实async,await相较于promise有个很大的缺点,他没有捕获错误的机制,所以需要自己人为去try,catch
async,await通过递归的方式实现了generator自动化执行next函数,等到done为true,结束递归,拿到async函数最终的结果,其实这也是co模块的实现原理
如果你对春招感兴趣,可以加我的个人微信:
Dolphin_Fung,我和我的小伙伴们有个面试群,可以进群讨论你面试过程中遇到的问题,我们一起解决
另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请”点赞+评论+收藏“一键三连,感谢支持!