📚 核心概念

1. 什么是 Promise?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Promise 三种状态
const states = {
PENDING: "pending", // 初始状态
FULFILLED: "fulfilled", // 操作成功完成
REJECTED: "rejected", // 操作失败
};

// 创建 Promise
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
if (Math.random() > 0.5) {
resolve("成功数据"); // 状态变为 fulfilled
} else {
reject("失败原因"); // 状态变为 rejected
}
}, 1000);
});

2. 状态特性

  • 不可逆:状态一旦改变就不能再变
  • 唯一性:只能是 pending → fulfilled 或 pending → rejected

🔧 Promise API 大全

1. 静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 快速创建
const resolved = Promise.resolve("立即成功");
const rejected = Promise.reject("立即失败");

// 并行处理
const urls = ["/api1", "/api2", "/api3"];

// 所有成功才算成功
Promise.all(urls.map((url) => fetch(url)))
.then((responses) => console.log("全部成功"))
.catch((error) => console.log("有一个失败"));

// 第一个完成(成功或失败)
Promise.race([fetch("/api1"), timeout(5000)]).then((response) =>
console.log("第一个完成的")
);

// 所有都完成(不管成功失败)
Promise.allSettled(urls.map((url) => fetch(url))).then((results) => {
results.forEach((result, index) => {
if (result.status === "fulfilled") {
console.log(`第${index}个成功:`, result.value);
} else {
console.log(`第${index}个失败:`, result.reason);
}
});
});

// 第一个成功
Promise.any(urls.map((url) => fetch(url)))
.then((response) => console.log("第一个成功的"))
.catch((errors) => console.log("全部失败"));

2. 实例方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
promise
.then(
(value) => {
/* 成功处理 */
}, // onFulfilled
(reason) => {
/* 失败处理 */
} // onRejected
)
.catch((reason) => {
/* 错误捕获 */
}) // 相当于 then(null, onRejected)
.finally(() => {
/* 最终执行 */
}); // 无论成败都会执行

⚡ 执行机制深度解析

1. 同步 vs 异步执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
console.log("1. 同步开始");

const promise = new Promise((resolve) => {
console.log("2. 执行器同步执行");
resolve("成功值"); // ← 立即将 onFulfilled 加入微队列
console.log("3. resolve 后的同步代码");
});

promise.then((value) => {
console.log("5. onFulfilled 微任务:", value);
});

console.log("4. 同步结束");

// 输出顺序:
// 1. 同步开始
// 2. 执行器同步执行
// 3. resolve 后的同步代码
// 4. 同步结束
// 5. onFulfilled 微任务: 成功值

2. 状态先确定,后注册 then

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
console.log("1. 开始");

// Promise 已经完成
const resolvedPromise = Promise.resolve("已完成的值");

// 稍后注册 then
setTimeout(() => {
console.log("2. 准备注册 then");

resolvedPromise.then((value) => {
console.log("4. then 回调立即执行:", value); // 立即进入微队列
});

console.log("3. then 注册完成");
}, 100);

console.log("同步结束");

// 输出:
// 1. 开始
// 同步结束
// 2. 准备注册 then
// 3. then 注册完成
// 4. then 回调立即执行: 已完成的值

3. 微任务优先级

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 宏任务
setTimeout(() => console.log("6. 宏任务"), 0);

// 微任务
Promise.resolve()
.then(() => console.log("3. 微任务 1"))
.then(() => console.log("4. 微任务 2"))
.then(() => console.log("5. 微任务 3"));

// 同步代码
console.log("1. 同步开始");
console.log("2. 同步结束");

// 输出顺序:
// 1. 同步开始
// 2. 同步结束
// 3. 微任务 1
// 4. 微任务 2
// 5. 微任务 3
// 6. 宏任务

🔄 Promise/A+ 规范核心

1. then 方法规范

1
promise.then(onFulfilled, onRejected);

规则

  • 参数可选,非函数忽略(值穿透)
  • 回调必须异步执行(微任务)
  • 无 this 绑定
  • 可多次调用,按注册顺序执行

2. 值穿透示例

1
2
3
4
5
6
7
8
9
10
11
12
Promise.resolve("hello")
.then() // 非函数被忽略
.then("world") // 非函数被忽略
.then(undefined) // 非函数被忽略
.then(console.log); // 输出: hello

// 等效于:
Promise.resolve("hello")
.then((value) => value)
.then((value) => value)
.then((value) => value)
.then((value) => console.log(value));

3. 链式调用规则

1
promise2 = promise1.then(onFulfilled, onRejected);

四种情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 1. onFulfilled 非函数
Promise.resolve("value1")
.then(null) // 非函数,穿透
.then((value) => console.log(value)); // value1

// 2. onRejected 非函数
Promise.reject("error1")
.then(null, null) // 非函数,穿透
.catch((error) => console.log(error)); // error1

// 3. 回调抛出异常
Promise.resolve("value2")
.then(() => {
throw new Error("oops");
})
.catch((error) => console.log(error.message)); // oops

// 4. 回调返回值
Promise.resolve("value3")
.then((value) => value + "!") // 返回新值
.then((value) => Promise.resolve(value + "!!")) // 返回 Promise
.then((value) => console.log(value)); // value3!!!

4. Promise 解决流程

1
2
3
4
5
6
7
8
9
10
11
12
13
// 循环引用检测
const promise = new Promise((resolve) => {
resolve(promise); // TypeError: Chaining cycle detected
});

// thenable 对象处理
const thenable = {
then: function (onFulfilled) {
onFulfilled("thenable value");
},
};

Promise.resolve(thenable).then((value) => console.log(value)); // thenable value

💡 高级特性与模式

1. 错误冒泡机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Promise.resolve()
.then(() => {
console.log("步骤1");
throw new Error("步骤1失败");
})
.then(() => {
console.log("不会执行"); // 被跳过
})
.catch((error) => {
console.log("捕获错误:", error.message); // 步骤1失败
return "恢复执行";
})
.then((value) => {
console.log("继续执行:", value); // 恢复执行
})
.finally(() => {
console.log("最终清理"); // 总是执行
});

2. 并行限制控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 控制并发数量的 Promise 池
class PromisePool {
constructor(maxConcurrent) {
this.maxConcurrent = maxConcurrent;
this.pending = [];
this.running = 0;
}

add(task) {
return new Promise((resolve, reject) => {
this.pending.push({ task, resolve, reject });
this.run();
});
}

run() {
if (this.running >= this.maxConcurrent || !this.pending.length) return;

this.running++;
const { task, resolve, reject } = this.pending.shift();

Promise.resolve(task())
.then(resolve, reject)
.finally(() => {
this.running--;
this.run();
});
}
}

// 使用示例
const pool = new PromisePool(3); // 最多3个并发
for (let i = 0; i < 10; i++) {
pool.add(() => fetch(`/api/data/${i}`));
}

3. 超时与重试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 超时控制
function withTimeout(promise, timeoutMs, timeoutMessage = "操作超时") {
const timeout = new Promise((_, reject) => {
setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
});
return Promise.race([promise, timeout]);
}

// 自动重试
function retry(fn, retries = 3, delay = 1000) {
return new Promise((resolve, reject) => {
const attempt = (attemptsLeft) => {
fn()
.then(resolve)
.catch((error) => {
if (attemptsLeft <= 0) {
reject(error);
} else {
console.log(`重试剩余 ${attemptsLeft} 次`);
setTimeout(() => attempt(attemptsLeft - 1), delay);
}
});
};
attempt(retries);
});
}

// 使用示例
retry(() => withTimeout(fetch("/api"), 5000), 3)
.then((response) => console.log("成功"))
.catch((error) => console.log("最终失败:", error));

4. 顺序执行模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 顺序执行 Promise 数组
function sequential(tasks) {
return tasks.reduce((promiseChain, currentTask) => {
return promiseChain.then((chainResults) =>
currentTask().then((currentResult) => [...chainResults, currentResult])
);
}, Promise.resolve([]));
}

// 使用示例
sequential([
() => Promise.resolve("任务1"),
() => Promise.resolve("任务2"),
() => Promise.resolve("任务3"),
]).then((results) => {
console.log("顺序执行结果:", results); // ['任务1', '任务2', '任务3']
});

🛠️ 实用工具函数

1. Promise 化回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 将回调风格函数转为 Promise
function promisify(fn) {
return function (...args) {
return new Promise((resolve, reject) => {
fn(...args, (error, result) => {
if (error) reject(error);
else resolve(result);
});
});
};
}

// 使用示例
const readFileAsync = promisify(fs.readFile);
readFileAsync("file.txt", "utf8").then((content) => console.log(content));

2. 批量处理控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 批量处理数组,控制并发
async function processBatch(items, processor, concurrency = 5) {
const results = [];
const batches = [];

for (let i = 0; i < items.length; i += concurrency) {
batches.push(items.slice(i, i + concurrency));
}

for (const batch of batches) {
const batchResults = await Promise.all(
batch.map(item => processor(item))
);
results.push(...batchResults);
}

return results;
}

// 使用示例
const urls = ['url1', 'url2', 'url3', ...];
processBatch(urls, fetch, 3)
.then(responses => console.log('批量处理完成'));

⚠️ 常见陷阱与最佳实践

1. 不要忘记 return

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ❌ 错误:忘记 return
Promise.resolve(1)
.then((value) => {
value + 1; // 没有 return,下一个 then 收到 undefined
})
.then((value) => {
console.log(value); // undefined
});

// ✅ 正确:显式返回
Promise.resolve(1)
.then((value) => {
return value + 1; // 显式返回
})
.then((value) => {
console.log(value); // 2
});

2. 及时错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
// ❌ 危险:未处理的 Promise 拒绝
const dangerousPromise = Promise.reject(new Error("未处理"));

// ✅ 安全:始终处理错误
const safePromise = Promise.reject(new Error("已处理")).catch((error) =>
console.error("安全处理:", error)
);

// ✅ 或者在全局处理
window.addEventListener("unhandledrejection", (event) => {
console.error("未处理的 Promise 拒绝:", event.reason);
event.preventDefault();
});

3. 避免 Promise 构造函数反模式

1
2
3
4
5
6
7
8
9
10
11
// ❌ 反模式:在 Promise 构造函数中使用异步操作
function badExample(url) {
return new Promise((resolve, reject) => {
fetch(url).then(resolve).catch(reject); // 不必要的包装
});
}

// ✅ 正确:直接返回 Promise
function goodExample(url) {
return fetch(url); // 直接返回现有的 Promise
}

🎯 性能优化技巧

1. 避免不必要的 Promise 创建

1
2
3
4
5
6
7
8
9
10
11
12
// ❌ 不必要的 Promise 包装
function unnecessary(value) {
return new Promise((resolve) => {
resolve(process(value)); // 同步操作不需要 Promise
});
}

// ✅ 直接返回值或使用 Promise.resolve
function optimized(value) {
const result = process(value);
return Promise.resolve(result); // 更轻量
}

2. 使用 Promise.all 优化并行操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ❌ 顺序执行(慢)
async function slow() {
const result1 = await fetch("/api1");
const result2 = await fetch("/api2");
const result3 = await fetch("/api3");
return [result1, result2, result3];
}

// ✅ 并行执行(快)
async function fast() {
const [result1, result2, result3] = await Promise.all([
fetch("/api1"),
fetch("/api2"),
fetch("/api3"),
]);
return [result1, result2, result3];
}

📊 总结表格

特性 说明 示例
状态 pending → fulfilled/rejected 不可逆
异步保证 then 回调总是异步 微任务队列
值穿透 非函数 then 参数被忽略 .then().then(console.log)
错误冒泡 错误沿链传递直到被捕获 .then().catch()
链式调用 then 返回新 Promise p.then().then()
并行处理 Promise.all/race/any 多个 Promise 协同