除了 Promise.all()
和 Promise.race()
,JavaScript 还提供了其他专门处理多个异步操作的 Promise 静态方法,以及一些基于 Promise 链式调用的模式,适用于不同的业务场景。以下是主要方法及使用场景:
一、Promise.allSettled():等待所有操作完成(无论成败)
Promise.allSettled()
会等待传入的所有异步操作全部完成(无论成功或失败),最终返回一个包含每个操作结果的数组。每个结果对象包含:
status
:"fulfilled"
(成功)或"rejected"
(失败)value
:成功时的结果(仅status
为fulfilled
时存在)reason
:失败时的原因(仅status
为rejected
时存在)
适用场景:
- 需要完整获取所有异步操作的结果(成功和失败都要处理),例如批量任务状态汇总(如批量上传文件后统计成功/失败数量)。
示例:
// 模拟多个异步操作(成功和失败混合)
const tasks = [
Promise.resolve("任务1成功"),
Promise.reject(new Error("任务2失败")),
new Promise(resolve => setTimeout(() => resolve("任务3成功"), 1000))
];
Promise.allSettled(tasks).then(results => {
results.forEach((result, index) => {
if (result.status === "fulfilled") {
console.log(`任务${
index + 1}成功:`, result.value);
} else {
console.error(`任务${
index + 1}失败:`, result.reason.message);
}
});
});
二、Promise.any():等待第一个成功的操作
Promise.any()
接收多个 Promise,等待第一个成功的操作并返回其结果;如果所有操作都失败,则返回一个包含所有失败原因的 AggregateError
错误。
适用场景:
- 从多个备选资源中优先使用第一个可用的结果(如多 CDN 资源加载,取第一个成功返回的资源)。
- 容错场景:允许部分操作失败,只要有一个成功即可继续执行。
示例:
// 模拟多个异步操作(1个成功,2个失败)
const apis = [
new Promise((_, reject) => setTimeout(() => reject("接口1超时"), 1000)),
new Promise(resolve => setTimeout(() => resolve("接口2返回数据"), 1500)),
new Promise((_, reject) => setTimeout(() => reject("接口3错误"), 2000))
];
Promise.any(apis)
.then(data => {
console.log("成功获取数据:", data); // 输出:接口2返回数据(1.5秒后)
})
.catch(errors => {
console.error("所有接口失败:", errors.errors); // 仅当所有操作失败时触发
});
三、串行执行多个异步操作(基于链式调用)
如果多个异步操作存在依赖关系(后一个操作需要前一个的结果),则需要按顺序执行,可通过 then()
链式调用或 async/await
实现(本质是 Promise 的链式特性)。
适用场景:
- 流程化异步任务(如先登录获取 token,再用 token 获取用户信息,最后用用户信息获取权限列表)。
示例(基于 then()
链式调用):
// 模拟依赖关系的异步操作
const fetchToken = () => Promise.resolve("user_token_123");
const fetchUser = (token) => Promise.resolve({
id: 1, name: "Alice", token });
const fetchPermissions = (userId) => Promise.resolve(["read", "write"]);
// 按顺序执行:先获取token → 再获取用户 → 最后获取权限
fetchToken()
.then(token => fetchUser(token))
.then(user => fetchPermissions(user.id))
.then(permissions => {
console.log("最终权限:", permissions); // 输出:["read", "write"]
});
示例(基于 async/await
,更直观):
async function getPermissions() {
const token = await fetchToken();
const user = await fetchUser(token);
const permissions = await fetchPermissions(user.id);
console.log("最终权限:", permissions);
}
getPermissions();
总结:方法对比与选择
方法 | 核心特性 | 适用场景 |
---|---|---|
Promise.all() |
所有成功则返回结果数组,一个失败则整体失败 | 依赖所有异步操作成功的场景(如数据汇总) |
Promise.race() |
第一个完成(无论成败)则返回其结果 | 超时控制、资源竞速(如接口超时处理) |
Promise.allSettled() |
等待所有完成,返回每个操作的状态和结果 | 需完整统计成功/失败的场景(如批量任务) |
Promise.any() |
第一个成功则返回其结果,全失败则报错 | 容错场景(如多资源备选加载) |
链式调用/async/await |
按顺序执行,后一个依赖前一个的结果 | 有依赖关系的异步流程(如分步操作) |
根据具体业务需求选择合适的方法,可以高效处理多异步场景,同时保证代码的可读性和健壮性。