示例驱动,每节最小可运行代码。Promise 代表一个异步操作的最终结果,三种状态:Pending → Fulfilled / Rejected(不可逆)。

1. 创建:new Promise

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random() > 0.5 ? resolve("成功") : reject(new Error("失败"));
  }, 100);
});
 
p.then(v => console.log(v)).catch(e => console.error(e.message));

2. 链式调用:.then / .catch / .finally

fetch("https://api.example.com/users/1")
  .then(res => {
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();                    // 返回 Promise,链继续
  })
  .then(user => user.name)                // 返回普通值,自动包装
  .then(name => console.log(name))
  .catch(err => console.error(err))       // 捕获链上任意一环的错误
  .finally(() => console.log("无论成败都执行"));

3. 静态快捷方法

Promise.resolve(42);              // 已兑现的 Promise,常用于统一异步接口
Promise.reject(new Error("boom")); // 已拒绝的 Promise
 
// 包装同步值,让调用方统一用 await/.then 处理
function getConfig() {
  return Promise.resolve({ port: 3000 });
}

4. 并发四方法

方法行为失败时机
Promise.all全部成功才成功,返回结果数组任一失败立即拒绝
Promise.allSettled等全部结束,返回每个 {status, value/reason}永不拒绝
Promise.race第一个结束(成或败)者胜出第一个失败即拒绝
Promise.any第一个成功者胜出全部失败才拒绝(AggregateError)
const ok = ms => new Promise(r => setTimeout(() => r(`done-${ms}`), ms));
const fail = ms => new Promise((_, j) => setTimeout(() => j(new Error(`err-${ms}`)), ms));
 
// all:全部成功
await Promise.all([ok(100), ok(200)]);        // ["done-100", "done-200"]
 
// all:一个失败 → 整体拒绝
await Promise.all([ok(100), fail(200)]);      // throw err-200
 
// allSettled:收集所有结果,不抛错
await Promise.allSettled([ok(100), fail(200)]);
// [{status:"fulfilled",value:"done-100"}, {status:"rejected",reason:err-200}]
 
// race:用于超时控制
await Promise.race([fetch(url), fail(3000)]); // 3s 超时
 
// any:多源竞速,全部失败才抛错
await Promise.any([fail(100), ok(200)]);      // "done-200"

5. async/await(Promise 语法糖)

async function load() {
  try {
    const res = await fetch("https://api.example.com/data");
    const data = await res.json();       // await 暂停,直到 Promise 落定
    return data;                         // async 函数返回值自动包装为 Promise
  } catch (err) {
    console.error(err);                  // 等价于 .catch()
  }
}

关键规则:await 只能在 async 函数(或模块顶层)内使用;async 函数总返回 Promise。

6. 串行 vs 并行

const slow = ms => new Promise(r => setTimeout(() => r(ms), ms));
 
// 串行:约 300ms(逐个等待)
const a = await slow(100);
const b = await slow(200);
 
// 并行:约 200ms(同时发起)
const [x, y] = await Promise.all([slow(100), slow(200)]);

7. 常见坑

7.1 忘记 return,链条断裂

// 错:箭头函数用了花括号却没 return,下一环拿到 undefined
fetch(url).then(res => { res.json() }).then(d => console.log(d)); // d 是 undefined
 
// 对:
fetch(url).then(res => res.json()).then(d => console.log(d));

7.2 循环中串行 await(慢)

// 慢:串行,N 次网络往返
for (const id of ids) {
  const data = await fetchItem(id);
}
 
// 快:先并行发起,再统一等待
const results = await Promise.all(ids.map(id => fetchItem(id)));

7.3 忘记处理拒绝 → UnhandledPromiseRejection

// 错:没有 .catch,Node 会警告甚至退出
doAsyncWork().then(console.log);
 
// 对:
doAsyncWork().then(console.log).catch(console.error);

8. 手动封装回调风格 API

const fs = require("fs");
 
function readFileAsync(path, enc) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, enc, (err, data) => (err ? reject(err) : resolve(data)));
  });
}
 
// 现代替代:util.promisify 或内置 Promise API
const { readFile } = require("node:fs/promises");
const { promisify } = require("node:util");
const readFileP = promisify(fs.readFile);

要点速记

  1. .then() 返回新 Promise → 可无限链式;花括号箭头函数记得 return
  2. 并行用 Promise.all,超时用 race,容错收集用 allSettled
  3. 无依赖的异步操作不要串行 await
  4. 每条链都要有 .catch()(或外层 try/catch)
  5. Node 核心模块已全面 Promise 化(fs/promises、timers/promises 等),优先使用