JavaScript中如何实现fetch递归流程与其他函数并行执行
问题根源
你当前遇到的两个流程完全串行、输出不交错的现象,是代码执行逻辑和JS事件循环调度规则不匹配导致的,核心有两个原因:
loadNextContainer是纯同步递归逻辑:从第一次调用开始,会一口气递归跑完5次,同步把所有fetch请求发出去,整个发请求的流程没有任何异步等待、交回执行权的环节,瞬间就把所有请求上下文推到了任务队列里- 执行队列的优先级差异:
loop1里的await null会把每次console.log(i)排到微任务队列,而fetch的响应处理是宏任务。事件循环的规则是先清空所有同步执行栈,再跑完所有微任务队列的内容,才会执行宏任务——所以就出现了:同步栈跑完(loadNextContainer全量发请求)→ 微任务队列清空(输出0-4)→ 执行宏任务(输出5个fetched)的固定顺序,完全没有交错可能。
调整方案
只需要两处小改动,就能实现自由交错的并行效果,不需要改写核心业务逻辑:
- 把
loadNextContainer改造为异步流程,每一次请求完成数据处理后,再递归发起下一次请求,让每一步执行都能把调度权交还给事件循环
改造后的代码:// 记得初始化计数器,避免未定义报错 let numberContainer = 0; async function loadNextContainer() { if (numberContainer > 4) { return; } const url = `sample_videos/container${numberContainer}`; try { const response = await fetch(url); const data = await response.blob(); console.log("fetched"); // 原有存数据、处理数据的逻辑保持不变 } catch (error) { console.error('Error:', error); } numberContainer++; // 等当前请求全流程处理完成,再发起下一次请求 await loadNextContainer(); } - 调整两个流程的启动方式:不要等一个流程完全跑完再启动另一个,要让两个异步任务同时挂载到事件循环上,按各自的实际耗时抢占执行权
会导致串行效果的错误启动写法:
可实现并行交错的正确启动写法:// 先等loop1全部执行完,再启动loadNextContainer,必然是固定顺序 await loop1(); await loadNextContainer();// 两个任务同时启动,不互相等待,谁先完成哪一步就先输出 loop1(); loadNextContainer();
补充说明
如果改完后发现loop1的输出还是整体排在fetch前面,是因为空的await null没有实际的异步等待延迟,循环执行速度远快于网络请求速度。如果要模拟真实数据处理的耗时,让交错效果更明显,可以把loop1里的await null替换为极小的延时逻辑,比如await new Promise(resolve => setTimeout(resolve, 100)),两个流程的输出顺序就会更随机自然。
内容的提问来源于stack exchange,提问作者badcode
相关产品推荐
相关产品推荐

