React中Promise.all与await未按预期暂停请求问题排查
问题原因分析
Promise.all版本的问题
你遍历过程中直接把api.post()的结果push进数组,而api.post()一旦调用就会立即发送请求。等你把所有Promise都塞进数组再调用Promise.all时,所有请求早就已经发出去了——Promise.all的作用只是等待所有请求完成,根本不会控制请求的发送时机。
async+map版本的问题
map方法会一次性遍历所有key,每个迭代里的async函数会被立即执行。虽然函数内部用了await,但这些async函数是并行运行的,彼此之间不会等待。就像你同时启动1000个带延迟的任务,每个任务自己会等,但它们是一起启动的,所以请求还是会同时发出去。
正确的请求控制实现
方案1:完全串行(一个接一个发请求)
用for...of循环替代map,它会等待前一个async操作完成后再执行下一个:
async function importProjects() { const keys = Object.keys(importFiles); for (const key of keys) { try { const response = await api.post(apiUrl() + "api/v2/addPin/", { pin: importFiles[key] }); console.log(response.data); } catch (err) { // 处理单个请求失败的情况,避免一个出错导致全部终止 console.error(`处理key ${key}时出错`, err); } } }
方案2:控制并发数(比如一次发5个请求)
如果不想完全串行,想提高效率又不想一次性发太多请求,可以用批量处理:
async function importProjects() { const keys = Object.keys(importFiles); const batchSize = 5; // 每次并发5个请求 for (let i = 0; i < keys.length; i += batchSize) { const batch = keys.slice(i, i + batchSize); await Promise.all( batch.map(key => api.post(apiUrl() + "api/v2/addPin/", { pin: importFiles[key] }) .then(res => console.log(res.data)) .catch(err => console.error(`处理key ${key}时出错`, err)) ) ); } }
内容的提问来源于stack exchange,提问作者Zak
相关产品推荐
相关产品推荐

