Promise.all与Promise.race对比分析
在Node.js异步编程中,Promise.all和Promise.race是两个经常被混淆的API。最近在项目中踩了一个坑,特此记录。
问题背景
项目需要同时请求多个API获取用户信息,原本使用Promise.all来并行处理,但发现响应时间异常。经过排查发现,当某个Promise rejected时,Promise.all会立即reject整个数组,这导致了性能瓶颈。
代码复现
// 测试Promise.all行为
const promises = [
Promise.resolve(1),
Promise.reject(new Error('error')),
Promise.resolve(3)
];
Promise.all(promises)
.then(result => console.log('all success:', result))
.catch(err => console.log('all failed:', err.message));
// 输出: all failed: error
// 测试Promise.race行为
Promise.race(promises)
.then(result => console.log('race success:', result))
.catch(err => console.log('race failed:', err.message));
// 输出: race failed: error
性能测试数据
通过实际测试发现:
- Promise.all在所有Promise都成功时性能最佳,但有一个失败就整体失败
- Promise.race在第一个Promise完成时立即返回,但可能返回错误结果
实际优化方案
// 使用Promise.allSettled替代
const results = await Promise.allSettled(promises);
const successful = results
.filter(result => result.status === 'fulfilled')
.map(result => result.value);
// 或者使用错误处理包装
async function safeAll(promises) {
const results = await Promise.all(
promises.map(p => p.catch(e => ({error: e})))
);
return results;
}
总结
在Node.js异步编程中,选择正确的Promise API至关重要。Promise.all适合需要所有操作都成功的场景,而Promise.race适合超时控制等场景。建议在实际项目中根据业务需求选择合适的API,并做好错误处理。
踩坑提醒:不要盲目使用Promise.all,要考虑失败处理和性能影响。

讨论