Promise按分组串行执行的自定义实现无法按组等待,原因是什么?
问题根因
你遇到的问题核心是async函数只要被调用就会立刻开始执行,和后续是否await没有关系。
你在_.range(0,100).map(async (item, index) => {})的阶段,就已经把100个async函数全部调用完成了,所有异步任务此时已经全部启动,自然不会等分组串行执行。你后续的chunk分组、Promise.all操作,只是在等待已经在运行的Promise完成,完全没有控制任务的启动时机。
修正方案
- 不要提前执行async函数,而是把任务封装为「返回Promise的函数」,到对应分组要执行的时候再调用函数启动任务
- 分组后先调用当前组的所有任务函数生成Promise数组,再用Promise.all等待执行完成
修正后可正常运行的代码如下:
(async() => { // 这里返回的是任务函数,不是直接执行的Promise const postTaskCreators = _.range(0, 100).map((item, index) => { return async () => { console.log(`${index}: starting`); // 此处可替换为实际的axios请求逻辑 return Promise.resolve(); } }); let i = 0; for (const taskGroup of _.chunk(postTaskCreators, 10)) { console.log(`*********************** GROUP ${i} SIZE ${taskGroup.length} ***********************`); // 仅当处理当前分组时,才调用函数启动所有任务 const taskPromises = taskGroup.map(task => task()); await Promise.all(taskPromises); i++; } })().catch((e) => { throw e; })
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
疑问解答
你提到的map返回Promise<void>[]是正确的,这些Promise在map遍历阶段就已经被创建并启动执行,和你后续是否await没有关系。只有当你把任务封装为待调用的函数时,才能精准控制任务的启动时机,实现分组串行执行的效果。
内容的提问来源于stack exchange,提问作者Daniel Kaplan
相关产品推荐
相关产品推荐

