ES10 中的 Promise.all()、Promise.race() 和 Promise.allSettled() 方法分析和比较

随着 JavaScript 前端技术的发展,异步编程方法变得越来越普及,Promise 已成为一种常用的处理异步操作的方式。在 ES10 之后,Promise 中引入了三个新的方法:Promise.all()、Promise.race() 和 Promise.allSettled(),它们向异步编程提供了更加灵活的解决方案。

本文将分别介绍这三个方法的用法、示例和特点,并从优劣和应用场景两个角度进行比较,帮助开发者更好地理解和使用这些方法。

Promise.all()

Promise.all() 可以将多个 Promise 实例包装成一个新的 Promise 实例,返回值是一个数组,数组中的值即为每个 Promise 实例的返回值。当这些 Promise 实例都成功时,返回的新 Promise 实例才算成功,其中只要有一个 Promise 实例失败,则新 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]
});

const promise4 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('four');
  }, 2000);
});

Promise.all([promise1, promise4]).then(values => {
  console.log(values); // 这行代码不会执行
}).catch(error => {
  console.error(error); // 输出: "four" (在两秒后)
});

注:Promise.all() 方法有一个特殊的行为,即在传入的 Promise 实例数组中有非 Promise 实例时,会自动将其转化为 Promise 实例。

Promise.race()

Promise.race() 方法的用法和 Promise.all() 类似,都是将多个 Promise 包装成一个新的 Promise 实例。不同的是,Promise.race() 的新 Promise 实例的状态是由数组中最先发生变化的 Promise 实例的状态决定的。也就是说,只要有一个 Promise 实例率先被成功或失败,新的 Promise 实例就会采用这个 Promise 实例的返回值或错误原因作为自己的返回值或错误原因。

示例代码:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('promise1');
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('error from promise2');
  }, 500);
});

Promise.race([promise1, promise2]).then(value => {
  console.log(value); // 输出 "promise1" (在一秒后)
}).catch(error => {
  console.error(error); // 输出 "error from promise2" (在0.5秒后)
});

Promise.allSettled()

Promise.allSettled() 方法不同于 Promise.all() 和 Promise.race(),它的新 Promise 实例即使有 Promise 实例状态是失败的,也不会抛出错误,而是循序渐进地执行每个 Promise 实例,并在所有 Promise 实例都返回后返回一个包含各 Promise 结果状态的对象数组。

示例代码:

const promise1 = Promise.resolve(1);
const promise2 = Promise.reject('rejected');
const promise3 = Promise.resolve(3);

Promise.allSettled([promise1, promise2, promise3]).then(results => {
  console.log(results);
  // 输出 [ { status: "fulfilled", value: 1 },
  //        { status: "rejected", reason: "rejected" },
  //        { status: "fulfilled", value: 3 } ]
});

比较

优劣

三个方法的结果类型不同,Promise.all() 在所有 Promise 实例成功时返回数组类型结果,当有一个 Promise 实例失败时则直接抛出错误;Promise.race() 和 Promise.allSettled() 在任意一个 Promise 实例成功或失败时都会进行相应的处理,不会直接抛出错误。从结果类型和异常处理方面来看,Promise.race() 和 Promise.allSettled() 更加灵活,适用范围更广。

应用场景

  • Promise.all(),适用于需要同时对多个可并行执行的异步任务进行控制,通常会在多个请求完毕后整合请求的结果使用。
  • Promise.race(),适用于只关心最先执行完毕的异步任务的结果,例如请求中有多个接口地址,只要有一个接口返回数据就可以使用,忽略其他的请求。
  • Promise.allSettled(),适用于一些极端的场景,需要了解所有 Promise 实例的执行情况,并忽略 Promise 实例的状态。

总结

Promise.all()、Promise.race() 和 Promise.allSettled() 这三个方法在 ES6 异步编程中具有重要的作用,新方法的引入使得 Promise 更加灵活多变,开发者可以根据自己的需求来选择使用其中的某一种或多种方式。在实际开发中,我们可以根据自己的实际需求来灵活应用这些方法,提高异步编程的效率,避免冗余的代码,从而更好地完成项目开发。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b20027add4f0e0ffb2f46e