JavaScript多层嵌套for await循环如何从性能角度进行优化?
代码性能优化方案
核心优化逻辑
原有代码的最大耗时问题是所有接口请求完全串行执行,总耗时等于所有单个请求耗时的总和。将请求改为并发执行后,服务端接收的总请求数不变,但总耗时会降低到接近单个请求的最长耗时,是性价比最高的优化方向。
原有代码问题梳理
- 误用
for await遍历同步枚举数组:Object.values返回的是普通同步数组,不需要使用for await遍历,额外增加了无意义的异步迭代开销 - 接口请求完全串行:每次必须等待上一个
getPagesCount请求返回后才会发起下一个请求,大部分时间浪费在网络等待上 - 代码存在语法错误:生成params对象时
format和page属性之间缺少逗号分隔
优化后代码
const categoryList = Object.values(CategoriesEnum); const formatList = Object.values(FormatsEnum); // 生成所有并发请求任务 const requestTasks = categoryList.flatMap(category => { return formatList.map(async (format) => { const totalPosts = await getPagesCount(category, format); const totalPages = Math.ceil(totalPosts.offsetPagination.total / 12); // 直接生成当前枚举组合对应的所有路径 return Array.from({ length: totalPages }, (_, idx) => ({ params: { category, format, page: idx + 1 } })); }); }); // 等待所有请求完成后打平数组得到最终路径 const pathGroups = await Promise.all(requestTasks); return pathGroups.flat();
补充优化建议
如果枚举取值数量非常多,一次性发起大量请求可能触发服务端限流,可以添加并发数控制,推荐使用轻量工具p-limit实现,示例如下:
import pLimit from 'p-limit'; const limit = pLimit(10); // 自定义最大并发请求数,比如设置为10 const categoryList = Object.values(CategoriesEnum); const formatList = Object.values(FormatsEnum); const requestTasks = categoryList.flatMap(category => { return formatList.map(format => limit(async () => { const totalPosts = await getPagesCount(category, format); const totalPages = Math.ceil(totalPosts.offsetPagination.total / 12); return Array.from({ length: totalPages }, (_, idx) => ({ params: { category, format, page: idx + 1 } })); })); }); const pathGroups = await Promise.all(requestTasks); return pathGroups.flat();
内容的提问来源于stack exchange,提问作者Or05230
相关产品推荐
相关产品推荐

