async/await已经是很常用的语法关键字了,它比直接使用Promise.then链式调用更加的优雅,废话不多说直接开始正题:
这里先上个async/await使用例子
// 用来等待n秒的函数,返回一个Promise,n秒后resolve
function wait(n) {
return new Promise(resolve => {
setTimeout(() => {
resolve('wait ' + n + 's')
}, n * 1000)
})
}
// 使用async/await
;(async function () {
console.log('start')
let r1 = await wait(1)
console.log(r1) // 1s后,输出 'wait 1s'
let r2 = await wait(2)
console.log(r2) // 再过2s,输出 'wait 2s'
return 'finish'
})().then(function(result){
// async函数会返回一个Promise,其执行完成后Promise状态转为fulfilled
console.log(result) // 输出 'finish'
})
实现自己的async/await
async/await的原理是借助generate来实现,使用yield关键字来实现await的等待效果
基于上面的使用例子,这里给出自己实现的async/await函数的测试用例
// 自己实现的async/await
myAsync(function *() {
console.log('start')
let r1 = yield wait(1)
console.log(r1) // 1s后,输出 'wait 1s'
let r2 = yield wait(2)
console.log(r2) // 再过2s,输出 'wait 2s'
return 'finish'
}).then((result) => {
console.log(result) // 输出 'finish'
})
废话不多说,直接给出代码
function myAsync(gen) {
// 判断是否是generate类型
gen = typeof gen === 'function' ? gen() : gen
if (!gen?.next) throw new Error('param is not a generate!')
// 结果要返回一个Promise
return new Promise((resolve, reject) => {
function next(value) {
// 参数value接受上一次yield的返回值,如果是Promise,则等待其状态转为fulfilled时再执行gen.next
Promise.resolve(value).then((pRet) => {
try {
let ret = gen.next(pRet) // 调用gen.next获得返回值
if (!ret.done) next(ret.value) // generate未完成,递归执行next
else resolve(ret.value) // generate执行完成,async函数返回的Promise执行resolve
} catch (e) {
reject(e)
}
}, (e) => reject(e))
}
next()
})
}
输出结果: