
await 不会延迟 Promise 的创建,只等待其完成;两个 new Promise 在定义时已立即启动定时器,因此 promise2 先于 promise1 完成,导致总耗时仅 4 秒而非预期的 6 秒。
`await` 不会延迟 promise 的创建,只等待其完成;两个 `new promise` 在定义时已立即启动定时器,因此 `promise2` 先于 `promise1` 完成,导致总耗时仅 4 秒而非预期的 6 秒。
在 JavaScript 异步编程中,一个常见误区是认为 await promiseX 会“触发”或“延迟启动”该 Promise。实际上,Promise 构造函数中的执行器(executor)函数会在 new Promise 被调用时立即同步执行——这意味着 setTimeout 在 Promise 创建瞬间就已开始计时,与后续是否 await 完全无关。
来看原始代码的问题根源:
const promise1 = new Promise((resolve) => {
setTimeout(() => { console.log("promise1"); resolve(); }, 4000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => { console.log("promise2"); resolve(); }, 2000);
});
async function main() {
await promise1; // 等待 promise1 完成(4s 后)
await promise2; // 但 promise2 已在 2s 时完成 → 立即继续
console.log("end");
}
执行时序如下:
- t=0ms:promise1 和 promise2 同时创建 → 两个 setTimeout 同时启动;
- t=2000ms:promise2 解决,但此时 main 仍在等待 promise1,因此 console.log("promise2") 执行,但 await promise2 尚未被触及;
- t=4000ms:promise1 解决 → await promise1 完成,main 继续执行下一行;
- 紧接着 await promise2 检查:promise2 已处于 fulfilled 状态 → 立即解析,不等待;
- console.log("end") 输出,全程耗时约 4 秒。
✅ 正确做法:将 Promise 的创建推迟到 await 语句执行时,即把 new Promise 封装为函数,在需要时调用:
const createPromise1 = () => new Promise(resolve => {
setTimeout(() => {
console.log("promise1");
resolve("promise1");
}, 4000);
});
const createPromise2 = () => new Promise(resolve => {
setTimeout(() => {
console.log("promise2");
resolve("promise2");
}, 2000);
});
async function main() {
const result1 = await createPromise1(); // t=0 → 启动 4s 计时
const result2 = await createPromise2(); // t=4s → 启动 2s 计时
console.log("end"); // t=6s 输出
}
main(); // 总耗时 ≈ 6 秒
? 关键总结:
- await 是「等待已存在 Promise 的状态变更」,不是「按需创建并等待」;
- 若需串行控制执行时机,请封装为函数(lazy initialization),避免提前实例化;
- 进阶替代方案:使用 Promise.all([p1, p2]) 并行等待两者完成(总耗时取最长者,即 4s),或结合 AbortController 实现更复杂的调度逻辑。
遵循这一原则,才能真正掌握 async/await 的可控性与可预测性。











