Promise.all() 和 Promise.race() 是 Promise 提供的两个重要的静态方法,它们用于处理多个 Promise 的并行执行,但行为和用途完全不同。
Promise.all()
基本概念
Promise.all() 接收一个 Promise 数组作为参数,返回一个新的 Promise。这个新的 Promise 会在所有输入的 Promise 都成功完成时才成功,返回的结果是所有 Promise 结果组成的数组(顺序与输入顺序一致)。如果任何一个 Promise 失败,Promise.all() 会立即失败,返回第一个失败的 Promise 的错误。
使用场景
- 需要同时发起多个独立的请求,并等待所有请求都完成
- 多个异步操作之间存在依赖关系,需要所有结果都准备好后才能继续
示例代码
javascriptconst promise1 = fetch('/api/user'); const promise2 = fetch('/api/posts'); const promise3 = fetch('/api/comments'); Promise.all([promise1, promise2, promise3]) .then(responses => { // 所有请求都成功 return Promise.all(responses.map(r => r.json())); }) .then(data => { console.log('所有数据:', data); }) .catch(error => { console.error('某个请求失败:', error); });
特点
- 并行执行: 所有 Promise 同时开始执行
- 顺序保证: 结果数组顺序与输入顺序一致
- 快速失败: 任何一个失败,整体立即失败
- 空数组: 如果传入空数组,立即返回成功
Promise.race()
基本概念
Promise.race() 同样接收一个 Promise 数组,返回一个新的 Promise。这个新的 Promise 会在第一个 Promise 完成(无论成功或失败)时立即完成,并返回第一个完成的 Promise 的结果或错误。
使用场景
- 设置超时机制
- 从多个数据源获取数据,使用最快返回的结果
- 竞争条件处理
示例代码
javascript// 超时示例 const fetchData = fetch('/api/data'); const timeout = new Promise((_, reject) => { setTimeout(() => reject(new Error('请求超时')), 5000); }); Promise.race([fetchData, timeout]) .then(response => console.log('数据获取成功')) .catch(error => console.error(error)); // 多数据源竞争示例 const source1 = fetch('https://api1.example.com/data'); const source2 = fetch('https://api2.example.com/data'); const source3 = fetch('https://api3.example.com/data'); Promise.race([source1, source2, source3]) .then(response => response.json()) .then(data => console.log('最快的数据源:', data));
特点
- 快速返回: 返回第一个完成的结果
- 状态继承: 成功或失败取决于第一个完成的 Promise
- 不确定性: 哪个 Promise 先完成是不确定的
- 空数组: 如果传入空数组,Promise 永远处于 pending 状态
对比总结
| 特性 | Promise.all() | Promise.race() |
|---|---|---|
| 完成条件 | 所有 Promise 都成功 | 第一个 Promise 完成 |
| 失败条件 | 任何一个 Promise 失败 | 第一个 Promise 失败 |
| 返回结果 | 所有结果的数组 | 第一个完成的结果 |
| 使用场景 | 需要所有结果 | 需要最快结果 |
| 执行方式 | 并行执行 | 并行执行 |
其他相关方法
Promise.allSettled()
ES2020 新增,等待所有 Promise 完成(无论成功或失败),返回每个 Promise 的状态和结果:
javascriptPromise.allSettled([promise1, promise2, promise3]) .then(results => { results.forEach(result => { if (result.status === 'fulfilled') { console.log('成功:', result.value); } else { console.log('失败:', result.reason); } }); });
Promise.any()
ES2021 新增,返回第一个成功的 Promise,如果所有 Promise 都失败,返回 AggregateError:
javascriptPromise.any([promise1, promise2, promise3]) .then(result => console.log('第一个成功:', result)) .catch(error => console.log('全部失败:', error));
实际应用建议
- 使用 Promise.all(): 当需要所有数据都准备好时,如加载多个必需的资源
- 使用 Promise.race(): 当只需要最快的结果时,如设置超时或从多个镜像源获取数据
- 使用 Promise.allSettled(): 当需要知道每个操作的结果,即使某些失败
- 使用 Promise.any(): 当只需要一个成功的结果,如从多个备份服务器获取数据