async await 语法是ES7出现的,是基于ES6的 promise和generator实现的,那么js底层是如何实现的呢,让promise异步状态变为await的同步写法。
async/await 是建立在Promise之上的语法糖,它的底层实现原理是基于状态机的转换和生成器(Generator)函数。下面我将详细描述其工作原理。
生成器函数(Generator)和迭代器(Iterator) 生成器函数可以暂停和恢复执行。当调用生成器函数时,它返回一个迭代器对象,通过调用迭代器的next()方法可以逐步执行生成器函数体。每次遇到yield关键字,函数就会暂停执行并返回一个值。
将异步操作转化为同步写法 async/await 通过暂停和恢复执行来实现异步操作的同步写法。async函数本质上是一个生成器函数,但使用了async关键字标记。await后面的表达式会被包装成Promise。
状态机的实现 编译器(如Babel)会将async函数转换成生成器函数的形式,然后使用一个状态机(通常由一个包装函数实现)来管理生成器的状态,自动执行迭代过程。
转换步骤:
假设有这样一个async函数:
javascriptasync function example() {
const result = await someAsyncCall();
console.log(result);
}
它会被转换成类似下面的生成器函数:
javascriptfunction example() {
return spawn(function* () {
const result = yield someAsyncCall();
console.log(result);
});
}
这里的spawn函数就是一个自动执行器,它会管理生成器的状态,处理Promise的解析,并继续执行生成器直到结束。
一个简化的自动执行器可能如下:
javascriptfunction spawn(generatorFunc) {
return new Promise((resolve, reject) => {
const generator = generatorFunc();
const step = (key, arg) => {
let result;
try {
result = generator[key](arg);
} catch (error) {
return reject(error);
}
const { value, done } = result;
if (done) {
return resolve(value);
}
// 确保返回一个Promise
Promise.resolve(value).then(
value => step('next', value),
error => step('throw', error)
);
};
step('next');
});
}
步骤解析:
spawn函数返回一个Promise,这样调用者可以使用.then()和.catch()。
创建生成器对象generator。 定义一个step函数,用于控制生成器的执行。它根据状态('next'或'throw')调用生成器的相应方法(generator.next()或generator.throw())。
在首次调用时,使用step('next')启动生成器。
每次执行生成器的next或throw方法,都会返回一个对象{ value, done },其中value是yield后面的表达式的值(通常是一个Promise),done表示生成器是否已经结束。
如果生成器未结束(done为false),则等待Promise解析(使用Promise.resolve来确保它是一个Promise),然后根据解析结果:
如果生成器结束(done为true),则解析外部的Promise(即整个async函数的Promise)为生成器函数返回的值(即return的值)。
在async函数中,错误通过try-catch捕获。在自动执行器中,当生成器内部出现错误(包括异步操作reject)时,我们使用generator.throw()将错误抛入生成器,这样生成器内部如果有try-catch,就能捕获错误。


本文作者:繁星
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!