async/await 是 Promise 的语法糖,底层基于 Promise 和微任务队列运行;async 函数必返回 Promise,await 将后续代码包装为微任务,在当前宏任务结束后执行。

async/await 不是新创建的异步机制,而是 Promise 的语法糖,其底层完全基于 Promise 和微任务队列(microtask queue)运行,执行逻辑严格遵循 JavaScript 的事件循环模型。
async 函数返回的是 Promise 对象
声明一个 async 函数时,JavaScript 引擎会自动将其包装为返回 Promise 的函数:
- 若函数正常返回值 v,等价于 Promise.resolve(v);
- 若函数抛出异常 e,等价于 Promise.reject(e);
- 即使函数体内没有 await,也一定返回 Promise —— 这是 async 的强制语义。
await 暂停执行但不阻塞线程
await 后面的表达式会被立即求值。如果结果是 Promise,则当前 async 函数的执行上下文被挂起,控制权交还给调用者;该 Promise 进入微任务队列等待解决。关键点在于:
- await 并非“让出线程”,而是将后续代码(即 await 之后的语句)包装成一个 then 回调,注册为微任务;
- 这个微任务会在当前宏任务(如 script、setTimeout 回调)结束后、下一轮宏任务开始前执行;
- await 后的代码不会在当前调用栈中继续执行,而是等到 Promise settled 后,在微任务阶段恢复执行上下文。
执行顺序由事件循环精确控制
下面这段代码能清晰体现底层调度逻辑:
立即学习“Java免费学习笔记(深入)”;
async function foo() {console.log('1');
await Promise.resolve();
console.log('2');
}
console.log('a');
foo();
console.log('b');
输出顺序是:a → 1 → b → 2。原因如下:
- 同步代码 'a' 和 'b' 在主 script 宏任务中立即执行;
- foo 内部 '1' 是同步执行的;
- await Promise.resolve() 触发微任务注册(即 console.log('2') 的回调);
- 主 script 宏任务结束后,清空微任务队列,执行 '2'。
错误处理本质是 Promise.catch
try/catch 在 async 函数中能捕获 await 后 Promise 的 rejection,是因为:
- await 表达式内部等价于 .then(onFulfilled).catch(onRejected);
- 引擎将 catch 块自动绑定到 await 所在 Promise 的拒绝路径上;
- 未被捕获的 await 错误最终表现为 async 函数返回的 Promise 被 reject,可被外层 .catch() 或顶层 unhandledrejection 监听。










