在前端开发中,异步操作是非常常见的。但是,当需要同时执行多个异步操作时,往往会遇到一些问题。例如,如何控制异步操作的数量,如何保证它们按照指定的顺序执行等等。在 ES2021 中,引入了一些新的语言特性,可以帮助我们实现异步多重限制方案,本文将详细介绍这些特性的使用方法。
Promise.allSettled()
Promise.all() 是一个非常常用的方法,可以用来将多个 Promise 实例组合成一个新的 Promise 实例,等待所有的 Promise 实例都执行完成后再返回结果。但是,如果其中某个 Promise 实例出现了错误,整个 Promise.all() 就会失败。在这种情况下,我们就需要使用 Promise.allSettled() 方法。
Promise.allSettled() 方法也可以将多个 Promise 实例组合成一个新的 Promise 实例,但是它不会在任何 Promise 实例失败时立即失败,而是会等待所有的 Promise 实例都执行完成后,返回一个包含每个 Promise 实例执行结果的数组。例如:
-- -------------------- ---- ------- ----- -------- - - ----------------------- ---- ------------------ ---------------- ----------------------- --- -- ---------------------------- ------------- -- - --------------------- -- ------------ -- - ------------------- ---
上面的代码中,Promise.allSettled() 方法接收一个包含三个 Promise 实例的数组,其中第二个 Promise 实例会返回一个错误。当所有的 Promise 实例都执行完成后,Promise.allSettled() 方法会返回一个包含三个对象的数组,每个对象都包含了对应 Promise 实例的执行结果。例如:
[ { status: 'fulfilled', value: 'result 1' }, { status: 'rejected', reason: Error: error }, { status: 'fulfilled', value: 'result 3' } ]
Promise.any()
Promise.any() 方法也是一个新的语言特性,用于将多个 Promise 实例组合成一个新的 Promise 实例,等待其中任何一个 Promise 实例成功后就返回成功结果。如果所有的 Promise 实例都失败了,Promise.any() 方法就会返回一个 AggregateError 对象,其中包含了所有 Promise 实例的错误信息。例如:
-- -------------------- ---- ------- ----- -------- - - ------------------ ------------ ----- -------------------------- ------------------ ------------ ---- -- --------------------- ------------ -- - -------------------- -- ------------ -- - ------------------- ---
上面的代码中,Promise.any() 方法接收一个包含三个 Promise 实例的数组,其中第二个 Promise 实例会返回一个成功结果。当其中任何一个 Promise 实例成功后,Promise.any() 方法就会返回一个成功结果,例如:
result
Promise.race()
Promise.race() 方法也是一个非常常用的方法,用于将多个 Promise 实例组合成一个新的 Promise 实例,等待其中任何一个 Promise 实例成功或失败后就返回对应的结果。例如:
-- -------------------- ---- ------- ----- -------- - - --- --------------- -- ------------- -- --------------- ---- ------- --- --------------- -- ------------- -- --------------- ---- ------- --- --------------- -- ------------- -- --------------- ---- ------ -- ---------------------- ------------ -- - -------------------- -- ------------ -- - ------------------- ---
上面的代码中,Promise.race() 方法接收一个包含三个 Promise 实例的数组,其中第一个 Promise 实例会在 1 秒后返回结果。当其中任何一个 Promise 实例成功或失败后,Promise.race() 方法就会返回对应的结果,例如:
result 1
async/await
async/await 是一个非常常用的异步编程语言特性,可以让我们像同步代码一样编写异步代码。在 ES2021 中,async/await 也有了一些新的特性,例如:
Promise.any() 和 Promise.allSettled() 的支持
async/await 支持使用 Promise.any() 和 Promise.allSettled() 方法,例如:
-- -------------------- ---- ------- ----- -------- --------- - ----- -------- - - ------------------ ------------ ----- -------------------------- ------------------ ------------ ---- -- --- - ----- ------ - ----- ---------------------- -------------------- - ----- ------- - ------------------- - --- - ----- ------- - ----- ----------------------------- --------------------- - ----- ------- - ------------------- - - ----------
上面的代码中,example() 函数中使用了 async/await 关键字,同时使用了 Promise.any() 和 Promise.allSettled() 方法来处理多个 Promise 实例。当其中任何一个 Promise 实例成功后,async/await 就会返回对应的结果;当所有的 Promise 实例都执行完成后,async/await 就会返回包含每个 Promise 实例执行结果的数组。
for-await-of 循环
for-await-of 循环是一个新的语言特性,可以用于遍历异步迭代器对象。例如:
-- -------------------- ---- ------- ----- -------- --------- - ----- ------------- - - ------------------------ - --- - - -- ------ - ----- ------ - -- -- - -- - ------ - ------ ---- ----- ----- -- - ------ - ----- ---- -- - -- - -- --- ----- ------ ----- -- -------------- - ------------------- - - ----------
上面的代码中,example() 函数中定义了一个异步迭代器对象 asyncIterable,并使用 for-await-of 循环遍历了它的所有值。当异步迭代器对象还有值时,for-await-of 循环就会执行异步操作,并等待异步操作完成后再进行下一次循环。
示例代码
下面是一个使用 Promise.allSettled() 和 async/await 实现异步多重限制方案的示例代码:
-- -------------------- ---- ------- ----- -------- --------- - ----- ---- - --- -- -- -- -- -- -- -- -- ---- ----- ----- - -- ----- -------- - --- --- ----- - -- ----- ------ - ------------ - ----- ----- - ----------------- ----- - ------- ----- ------------- - --------------- ---- -- - ----- --- --------------- -- ------------------- ------- ------ ---- - -- --- ------------------------------------------------- ----- -- ------ - ----- ------- - ----- ---------------------- ----- ----------- - --------------- ----- ------ - ----------- -------------- -- ------------- --- ------------ ----------- -- -------------- -------------------- - ----------
上面的代码中,example() 函数中定义了一个包含 10 个数字的数组 data,同时定义了一个限制并发数量的变量 limit。在 while 循环中,将数组 data 按照 limit 的数量拆分成多个 chunk,每个 chunk 中的数字都会执行一个异步操作,并返回它的值的两倍。最终,使用 Promise.allSettled() 方法将所有的 chunkPromise 组合成一个 Promise 实例,并使用 Promise.all() 方法等待所有的 Promise 实例都执行完成后,返回每个 Promise 实例执行结果的数组。最后,使用 flat() 和 filter() 方法过滤出成功的 Promise 实例,并将它们的值保存到一个新的数组中。当所有的异步操作执行完成后,会将这个新的数组输出到控制台上。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d99681a941bf713414671d