示例驱动,每节最小可运行代码。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);要点速记
.then()返回新 Promise → 可无限链式;花括号箭头函数记得return- 并行用
Promise.all,超时用race,容错收集用allSettled - 无依赖的异步操作不要串行
await - 每条链都要有
.catch()(或外层try/catch) - Node 核心模块已全面 Promise 化(
fs/promises、timers/promises等),优先使用