async / await 原理
1. 明确概念
async 函数就是 Generator 函数的语法糖。把 Generator 函数的 * 换成 async,把 yield 替换成 await。
2. async 对 Generator 的改进
- 内置执行器:不需要使用
next()手动执行。 await后面的值更广:可以是 Promise 对象或原始类型的值;yield命令后面只能是 Thunk 函数或 Promise 对象。- 返回值是 Promise:返回非 Promise 时,
async函数会把它包装成 Promise 返回(Promise.resolve(value))。- 若
async中没有return,返回的是Promise<undefined>。 - 若有
return:return 的值会作为返回 Promise 的then回调值。
- 若
3. 作用
异步编程的终极解决方案。
4. 通俗理解
async/await 是异步编程回调函数写法的替代方法——使代码以同步方式的写法完成异步操作。
5. 原理示例
// 用 Generator + 自动执行器模拟 async/await
function asyncToGenerator(genFunc) {
return function () {
const gen = genFunc.apply(this, arguments);
return new Promise((resolve, reject) => {
function step(key, arg) {
let res;
try { res = gen[key](arg); }
catch (e) { return reject(e); }
const { value, done } = res;
if (done) return resolve(value);
Promise.resolve(value).then(
(v) => step('next', v),
(e) => step('throw', e),
);
}
step('next');
});
};
}
const fetchUser = asyncToGenerator(function* () {
const data = yield new Promise(r => setTimeout(() => r('Tom'), 100));
console.log(data); // 'Tom'
});
fetchUser();
补充:
await后跟非 Promise 值,会被Promise.resolve包装。await后面的 Promise 若 reject,会"穿透" try/catch 抛到外层,不会继续往下执行。- 多个
await会串行执行,若彼此无依赖应改用Promise.all以提高并发性能。 - 循环中
await时,若希望并发请求所有数据后再进入下一步,可以先Promise.all(arr.map(asyncFn))。
来源整理自:vue3js.cn 面试官系列



