MST
星途 面试题库

面试题:Node.js中Promise.all与Promise.race的应用场景及原理

在Node.js项目开发中,什么时候适合使用Promise.all,什么时候适合使用Promise.race?请结合具体代码示例,阐述它们的实现原理以及可能出现的问题。
41.9万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

Promise.all

  • 适用场景:当你需要并行执行多个Promise,并且等待所有Promise都完成后再继续下一步操作时,适合使用Promise.all。例如,同时发起多个网络请求获取不同的数据,然后将这些数据汇总处理。
  • 实现原理Promise.all接受一个Promise数组作为参数,返回一个新的Promise。新Promise会在所有传入的Promise都变为resolved状态时,以一个包含所有Promise解析值的数组形式resolved;如果其中任何一个Promise被rejected,新Promise就会立即rejected,并将第一个被rejected的Promise的理由作为自己的理由。
  • 代码示例
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3])
 .then(values => {
    console.log(values); // [1, 2, 3]
  })
 .catch(error => {
    console.error(error);
  });
  • 可能出现的问题:如果数组中某个Promise长时间未完成(例如网络请求超时等原因),Promise.all会一直处于pending状态,导致后续依赖这些结果的操作无法继续执行。如果其中一个Promise被rejected,无法获取其他已经resolved的Promise的结果。

Promise.race

  • 适用场景:当你需要并行执行多个Promise,并且只关心第一个完成(无论resolved还是rejected)的Promise结果时,适合使用Promise.race。例如,同时发起多个相同功能的网络请求,只要有一个请求成功就使用该结果,忽略其他请求。
  • 实现原理Promise.race同样接受一个Promise数组作为参数,返回一个新的Promise。新Promise会在数组中任何一个Promise率先改变状态(resolvedrejected)时,以相同的状态和值(或理由)resolvedrejected
  • 代码示例
const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('First resolved');
  }, 100);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Second resolved');
  }, 50);
});

Promise.race([promise1, promise2])
 .then(value => {
    console.log(value); // 'Second resolved'
  })
 .catch(error => {
    console.error(error);
  });
  • 可能出现的问题:由于只关注第一个完成的Promise,其他Promise可能还在后台继续执行,可能会造成资源浪费,特别是如果这些Promise执行的操作比较消耗资源(如大数据计算、长时间网络请求等)。如果第一个完成的Promise是rejected状态,而后续有更有意义的resolved的Promise,会错过这些结果。