JavaScript中基于async/await的Promise多API调用逻辑及效率咨询
代码问题分析与优化方案
现有代码核心问题
你代码运行慢的核心原因不是嵌套循环,是以下几个问题:
- 请求完全串行:每一次
await都会等待前一个请求响应后才发起下一个请求,拉取n页的总耗时等于n个请求的耗时之和,这是速度慢的最大诱因。 - 存在逻辑bug:
getNextPages函数的循环内一直请求初始传入的nextUrl,没有使用接口返回的nextPage变量,会重复请求同一页,你说功能正常应该是写示例时手误写错了。 - 错误处理不合理:子函数内catch错误仅打印,会返回
undefined,父函数执行concat时会出现逻辑异常。 - 冗余代码:内层循环逐个push数组元素没有必要,可直接用数组合并方法简化。
优化实现
如果分页规则可提前确定(比如你用到的swapi接口,分页参数为page,从1开始递增),可以直接构造所有分页请求,用Promise.all并行发送,总耗时仅等于最慢的单个请求耗时,速度提升非常明显:
async function getData(url, numOfPages) { try { // 构造所有需要请求的分页地址,首页为原地址,后续页拼接page参数 const requestList = Array.from({ length: numOfPages + 1 }, (_, i) => { return i === 0 ? url : `${url}?page=${i + 1}` }).map(requestUrl => axios.get(requestUrl)) // 并行发送所有请求 const responses = await Promise.all(requestList) // 合并所有分页的返回结果 const finalData = responses.flatMap(res => res.data.results) finalData.forEach(item => console.log(item.name)) return finalData } catch (err) { console.error('请求异常:', err) throw err } } getData('https://swapi.dev/api/planets/', 3)
如果接口的下一页地址只能通过上一页的返回结果获取,无法提前构造所有分页地址,可以先修复原代码的逻辑bug,去除冗余逻辑:
async function getData(url, numOfPages) { try { let currentUrl = url let finalData = [] // 总请求数 = 1(首页) + 额外拉取页数 for (let i = 0; i <= numOfPages; i++) { const res = await axios.get(currentUrl) finalData.push(...res.data.results) currentUrl = res.data.next if (!currentUrl) break } finalData.forEach(item => console.log(item.name)) return finalData } catch (err) { console.error('请求异常:', err) throw err } }
如果需要兼容部分请求失败仍返回已成功拉取的数据,可以把Promise.all替换为Promise.allSettled,处理响应时过滤掉失败的请求即可。
核心优化点
- 用并行请求替代串行请求,大幅降低总耗时
- 修复重复请求同一页的逻辑bug
- 简化数组合并逻辑,去除冗余嵌套循环
- 统一错误处理,避免错误被吞导致的上层逻辑异常
- 合并冗余的子函数,代码结构更简洁易维护
内容的提问来源于stack exchange,提问作者user3570070
相关产品推荐
相关产品推荐

