前言
对于异步编程来说, async/await大大简化了异步操作,异步操作可以写成同步写法,如果不了解 async/await 可以点击🔗MDN async 函数了解更多关于 async 知识
编译async/await
在平时工作中,可能会遇到 async/await,比如有这样的例子

把 a 函数定义为async ,同时在内部使用 await,并把 await 的返回结果作为普通函数 b 的实参
来看这个 async 函数 a 编译后的代码

解析
首先在 async 的函数 a 中,返回了 __awaiter 函数的返回值,并在函数内部传递了4个实参,分别是 this,undefined,undefined,function *
🔔 其中
void 0可以看做不可变undefined,因为undefined不是关键字,可以被修改,所以使用void 0来代替undefined
在 __awaiter 是一个高阶函数,在内部返回了一个 Promise
new (P || P = new Promise)(function(){}), 由于 P 是undefined,所以P被赋值给Promise
在 Promise 内部中,默认执行了 step 方法,同时把 第四个参数 (即一个生成器函数 执行后的 next 对象) 作为实参传递给 step,如果不理解生成器函数的返回结果,可以看下面的例子简单了解一下,更多细节请查看🔗MDN关于# function*
js
function* gen() {
yield 10;
x = yield "foo";
yield x;
}
var gen_obj = gen();
// { value: 10, done: false }
console.log(gen_obj.next()); // 执行 yield 10
// { value: 'foo', done: false }
console.log(gen_obj.next()); // 执行 yield 'foo'
// { value: 100, done: false }
console.log(gen_obj.next(100)); // 将 100 赋给上一条 yield 'foo' 的左值,即执行 x=100,返回 100
// { value: undefined, done: true }
console.log(gen_obj.next()); // 执行完毕,value 为 undefined,done 为 true
以下解释来自
🔗MDN
调用一个生成器函数 并不会马上执行它里面的语句,而是返回一个这个生成器的 迭代器 ( iterator )对象 。当这个迭代器的next()方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield的位置为止,yield后紧跟迭代器要返回的值。或者如果用的是yield*(多了个星号),则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。
next()方法返回一个对象,这个对象包含两个属性:value 和 done,value 属性表示本次yield表达式的返回值,done 属性为布尔类型,表示生成器后续是否还有yield语句,即生成器函数是否已经执行完毕并返回。
调用next()方法时,如果传入了参数,那么这个参数会传给上一条执行的 yield 语句左边的变量
❤️简单来说,通过执行 function* 返回一个迭代器对象, 这个对象有 next 方法,每调用一次 next 方法,就会执行到遇到 yield为止,然后返回一个包含 value 字段和 done 字段 的对象, value 字段代表本次 yield 的返回值,done 表示是否完成,再次调用,遇到下个 yield 会再次停止
function * 其实就是让程序员控制函数的执行步骤
回到 step 函数上来, 那么只要是 done 为 true 的情况,说明 生成器函数 已经执行完毕,这时候 Promise 就可以结束了,如果没有结束,那么就需要不断的执行迭代器,直到 done 为 true
剩下的就是不断执行器,直到 done 为 true
执行 adopt 这个辅助方法,传入执行迭代器 返回的值,adopt 返回 Promise,然后再把 resolve 后的值传递给内部的 fulfilled 方法,在 fulfilled 中继续执行 step 方法
由于 P 是 void 0,所以 P 被赋值为
Promise,adopt定义为Promise是为了解决异步问题
根据核心逻辑作了一些简化

js
var __awaiter = function (thisArg, generator) {
return new Promise(function (resolve) {
function step(result) {
// 为 true 说明执行完毕,直接结束
result.done
? resolve(result.value)
// 再次创建一个 Promise,因为 Promise 可以处理异步,然后递归执行 step 方法
: Promise.resolve(result.value).then((res)=>step(generator.next(res)));
}
step((generator = generator.apply(thisArg, undefined)).next());
});
};
// async function a() {
// let r = await 1;
// await 2;
// return b(r)
// }
// function b(r){
// return r
// }
//
// a().then(res=>{
// console.log(res)
// })
//
function a() {
return __awaiter(this,function* () {
let r = yield 1;
yield 2;
return b(r);
});
}
function b(r) {
return r;
}
a().then(res => {
console.log(res);
});
最后看一道面试题来加强对 async /await 的认识

碰见 async 就当做普通函数对待,因为只有 await 才会被转化为 yield, 所以 asyncfn1 可以看做
js
function asyncfn1(){
return __awaiter(this,function* () {
console.log(2)
let r = yield asyncfn2();
console.log(3)
});
}
由于 __awaiter 方法中迭代器函数会被默认执行一次,即 step(generator = generator.apply(thisArg, undefined)).next()),因为 console(2) 在 yield 前面,不受 yield 影响,所以会同步输出, 同样的 asyncfn2 也是同样的道理
所以最终结果是 1 2 4 5 3 6