前言
在前端开发中,我们经常需要处理异步请求,而 Promise 是一种非常实用的异步编程解决方案。ES6 以前的 Promise 只提供了一些基础功能,而 ES11 中新增了 Promise.all() 和 Promise.allSettled() 两个方法,为我们的异步编程带来了更多的便利。本文将详细介绍这两个方法的区别和应用场景。
Promise.all()
Promise.all() 方法接受一个 Promise 实例数组作为参数,返回一个新的 Promise 实例。当参数数组中所有的 Promise 实例状态都变为 resolved 时,新的 Promise 实例状态也变为 resolved,并返回这些 Promise 实例的返回值数组。如果参数数组中任意一个 Promise 实例状态变为 rejected,则新的 Promise 实例状态也变为 rejected,并返回该 Promise 实例的返回值。
const p1 = Promise.resolve(1); const p2 = Promise.resolve(2); const p3 = Promise.resolve(3); Promise.all([p1, p2, p3]).then(values => { console.log(values); // [1, 2, 3] });
在上述代码中,我们将三个状态为 resolved 的 Promise 实例传入 Promise.all() 方法中,得到一个新的 Promise 实例,并通过 then() 方法获取到 Promise 实例的返回值数组。
Promise.allSettled()
Promise.allSettled() 方法接受一个 Promise 实例数组作为参数,返回一个新的 Promise 实例。与 Promise.all() 不同的是,即使参数数组中任意一个 Promise 实例状态变为 rejected,新的 Promise 实例也不会变为 rejected,而是等所有 Promise 实例都变为 settled 状态(即 fulfilled 或 rejected)后,再根据每个 Promise 实例的状态返回一个对象数组,每个对象表示一个 Promise 实例状态。
-- -------------------- ---- ------- ----- -- - ------------------- ----- -- - ------------------ ----- -- - ------------------- ----------------------- --- ----------------- -- - --------------------- -- - -- -------- ------------ ------ --- -- -------- ----------- ------- --- -- -------- ------------ ------ -- -- - ---
在上述代码中,我们将三个状态为 resolved 和 rejected 的 Promise 实例传入 Promise.allSettled() 方法中,得到一个新的 Promise 实例,并通过 then() 方法获取到每个 Promise 实例的状态和返回值(如果有的话)。
应用场景
Promise.all()
常见的应用场景包括同时获取多个远程数据、多个异步请求依赖于同一个数据等。
const userPromise = fetch('/user'); const articlePromise = fetch('/article'); const commentPromise = fetch('/comment'); Promise.all([userPromise, articlePromise, commentPromise]).then(results => { const [user, article, comment] = results; // Do something with user, article and comment });
在上述代码中,我们使用 fetch() 方法获取三个远程数据,传入 Promise.all() 方法中,并在 Promise 实例的返回值数组中使用解构赋值获取每个 Promise 实例的返回值,供后续业务处理使用。
另外,我们也可以使用 Promise.all() 优雅地实现多个异步请求依赖于同一个数据:
const fetchData = async () => { const data = await fetch('/data'); const result = await Promise.all([fetch(`/detail/${data.id}`), fetch(`/comment/${data.id}`)]); // Do something with result };
在上述代码中,我们先获取一个数据,然后使用 Promise.all() 方法同时发起两个依赖于该数据的异步请求,并使用结果 result 进行后续业务处理。
Promise.allSettled()
常见的应用场景包括事件上报、多个数据提交等。
例如,我们需要统计某个事件在多个页面的上报情况,我们可以使用 Promise.allSettled() 方法:
const report = async (eventId) => { const reportPromises = [reportToPage1(eventId), reportToPage2(eventId), reportToPage3(eventId)]; const results = await Promise.allSettled(reportPromises); // Do something with results };
在上述代码中,我们定义一个 report() 函数,用于统计某个事件在多个页面的上报情况。我们创建了一个 reportPromises 数组,其中每个元素表示向不同页面上报事件的 Promise 实例。将该数组传入 Promise.allSettled() 方法中,得到一个结果数组,供后续业务处理使用。
另外,我们也可以使用 Promise.allSettled() 方法实现多个数据提交,并根据每个数据的提交状态做出相应的操作:
const submitData = async (data) => { const submitPromises = [submitData1(data), submitData2(data), submitData3(data)]; const results = await Promise.allSettled(submitPromises); const successResults = results.filter(result => result.status === 'fulfilled'); const errorResults = results.filter(result => result.status === 'rejected'); // Do something with successResults and errorResults };
在上述代码中,我们定义一个 submitData() 函数,用于提交多个数据。我们创建了一个 submitPromises 数组,其中每个元素表示向不同服务器提交数据的 Promise 实例。将该数组传入 Promise.allSettled() 方法中,得到一个结果数组,分别提取提交成功和提交失败的 Promise 实例结果,供后续业务处理使用。
总结
ES11 中的 Promise.all() 和 Promise.allSettled() 为我们的异步编程带来了更多的便利。两个方法的区别在于 Promise.all() 在参数数组中任意一个 Promise 实例状态变为 rejected 时,新的 Promise 实例也会变为 rejected;而 Promise.allSettled() 则会等所有 Promise 实例变为 settled 状态后,再根据每个 Promise 实例的状态返回一个对象数组。常见的应用场景包括同时获取多个远程数据、多个异步请求依赖于同一个数据、事件上报、多个数据提交等。当我们在实际项目中遇到类似的问题时,可以优先考虑使用 Promise.all() 和 Promise.allSettled() 方法进行解决。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64b3b2a048841e9894ff1310