Promise 与 async/await

23 阅读2分钟

🔥 Promise

Promise 是一个“未来值”的状态机 + 异步回调容器。

主要做三件大事:

  1. 把异步结果封进一个对象(pending → fulfilled/rejected)
  2. 状态只能单向流转
  3. 所有回调(then/catch)都被塞进 microtask 队列执行

所以 Promise 并不是“执行异步”,而是“组织和调度异步”。

⚠️ Promise 常见踩坑

❌ 1. 链式没有自动中断

Promise.resolve()
  .then(() => { throw new Error('oops') })
  .then(() => console.log('still?'))

要想中断链式调用,必须 return rejected promise

❌ 2. then 的 return ≠ 外层函数 return

function a() {
  return Promise.resolve().then(() => 123)
}

console.log(a()) // 打印的永远是 Promise

❌ 3. await 写法不一定并发

await foo();
await bar(); // → 并没有并发,纯串行

正确并发:

await Promise.all([foo(), bar()]);

❌ 4. Promise 内 throw 与外部 throw 不是一回事

内部 throw → rejected
外部 throw → 程序直接炸

⚡ async/await

async/await = 用同步语法包装异步逻辑。 底层仍然是 Promise + microtask。

具体来说:

  1. async 会把返回值自动包成 Promise
  2. await 会“暂停”当前 async 函数,把后续拆成 then
  3. 并不会阻塞线程,只是代码被拆开
  4. async/await 不改变事件循环本质

⚠️ async/await 的常见踩坑

❌ 1. await 会让并发变串行

await foo();
await bar();

❌ 2. await 不会自动捕获异常

await Promise.reject('err'); // 不 try/catch 会直接抛

❌ 3. async 函数返回的一定是 Promise

async function a() { return 1; }

❌ 4. forEach + await = 陷阱现场

arr.forEach(async item => { await do(item); });

→ forEach 不会等你。
正确写法:

顺序执行:

for (const item of arr) await do(item);

并行执行:

await Promise.all(arr.map(do));

🎯 两者的区别

维度Promiseasync/await
风格链式回调同步化写法
本质状态机 + 回调队列Promise 语法糖
错误处理then/catchtry/catch
可读性容易嵌套清晰直观
并发Promise.all/race仍需配合 Promise
堆栈更碎更连续

Promise 解决异步结果表达;async/await 解决异步写法难看。

Promise 是底层机制,async/await 是表现形式
异步世界里,它俩谁都离不开谁。