Promise.all()、Promise.race()、Promise.allSettled()区别?

在处理多个并发异步操作时,Promise提供了几个关键的组合方法:Promise.all()Promise.race()Promise.allSettled()。它们都接收一个Promise可迭代对象,但返回的时机和结果处理逻辑截然不同,适用于不同的并发控制场景。

Promise.all():全部成功或快速失败

Promise.all()在所有输入的Promise都成功兑现(fulfilled)时,返回一个兑现的Promise,其结果是所有输入Promise结果的数组,顺序与输入一致。如果其中任何一个Promise被拒绝(rejected),则Promise.all()会立即变为拒绝状态,并返回该拒绝原因。

const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.reject('出错');

Promise.all([p1, p2])
  .then(results => console.log('全部成功:', results)) // [1, 2]
  .catch(e => console.log('有失败:', e));

Promise.all([p1, p2, p3])
  .then(results => console.log('不会执行'))
  .catch(e => console.log('捕获到第一个错误:', e)); // '出错'

这适用于多个彼此依赖、必须全部成功的并行任务,比如同时加载多个核心资源。

Promise.race():竞速,取首个落定者

Promise.race()返回一个Promise,其状态和结果与第一个状态落定(无论是兑现还是拒绝)的输入Promise相同。它不关心其他Promise的最终结果。

const fast = new Promise(res => setTimeout(() => res('快的'), 100));
const slow = new Promise(res => setTimeout(() => res('慢的'), 500));
const error = new Promise((_, rej) => setTimeout(() => rej('错误'), 200));

Promise.race([fast, slow])
  .then(winner => console.log('赢家是:', winner)); // '快的'

Promise.race([fast, error])
  .then(winner => console.log('不会执行'))
  .catch(e => console.log('捕获到错误:', e)); // '错误'

这常用于设置超时控制,或者从多个冗余服务中获取最先响应的结果。

Promise.allSettled():等待所有尘埃落定

Promise.allSettled()会等待所有输入的Promise都最终落定(每个都兑现或拒绝)。它返回一个兑现的Promise,其结果是描述每个输入Promise最终状态和值的对象数组。

const resolved = Promise.resolve(42);
const rejected = Promise.reject('error');

Promise.allSettled([resolved, rejected])
  .then(results => {
    results.forEach(result => console.log(result.status, result.value || result.reason));
  });
// 输出:
// fulfilled 42
// rejected error

每个结果对象都有一个status属性(‘fulfilled’‘rejected’)。如果状态是‘fulfilled’,则结果包含value;如果是‘rejected’,则包含reason。这适用于你需要知道所有异步操作最终结果,无论成败的场景,例如批量提交表单或收集多个API调用的最终状态。

选择合适的方法取决于你的业务逻辑。需要“全部成功”时用all();需要“第一个结果”时用race();需要“所有最终结果”时用allSettled()。还有一个Promise.any()(ES2021),它与race类似,但只关心第一个成功的结果,会忽略所有拒绝,直到全部失败。合理运用这些组合器能让异步流程控制更加清晰有力。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

    暂无评论内容