如何将Promise.all改为逐个发送请求实现分块数据串行上传
解决分块数据串行上传问题
你遇到的情况很常见——Promise.all()会一次性发起所有上传请求,服务器因并发压力过大超时。要改成逐个串行上传,这里有两种直观可行的方案,我帮你调整代码并解释逻辑:
方案一:用async/await + for...of实现(可读性最高)
如果你的项目支持ES2017+语法(或已通过Babel转译),这个写法最容易理解和调试:
async function uploadChunksSequentially() { const chunks = _.chunk(variableRecords, 30); const updateRes: boolean[] = []; // 逐个遍历分块,前一个上传完成再发起下一个 for (const chunk of chunks) { const uploadStatus = await this.portalService.updateDataForChart(variableId, chunk); updateRes.push(uploadStatus); // 可选:如果服务器需要缓冲时间,加个短暂延迟 // await new Promise(resolve => setTimeout(resolve, 150)); } // 原逻辑不变:所有块上传成功才执行后续请求 if (updateRes.every(updateStatus => updateStatus)) { return this.executeRequest<HealthDataSource, boolean>({ path: `/variable/user/datasources/${dataSource.identifier}`, method: 'PUT', body: { libelle: dataSource.datasource.libelle, type: dataSource.datasource.type, lastSyncDate: Math.max(maxDate, dataSource.datasource.lastSyncDate) }, headers: this.getHeaders() }); } else { return false; } } // 调用异步函数并返回Promise,保留原代码的返回结构 return uploadChunksSequentially().catch(err => { console.error('分块上传失败:', err); return false; });
方案二:用Array.reduce构建Promise链(兼容旧环境)
如果需要兼容不支持async/await的环境,可以用reduce把上传任务串成链式Promise:
const chunks = _.chunk(variableRecords, 30); // 用reduce串行执行每个上传任务,同时收集结果 return chunks.reduce((promiseChain, chunk) => { return promiseChain.then(uploadResults => { return this.portalService.updateDataForChart(variableId, chunk) .then(status => [...uploadResults, status]); }); }, Promise.resolve([])) // 初始化为空结果数组,启动链式调用 .then((updateRes: boolean[]) => { if (updateRes.every(updateStatus => updateStatus)) { return this.executeRequest<HealthDataSource, boolean>({ path: `/variable/user/datasources/${dataSource.identifier}`, method: 'PUT', body: { libelle: dataSource.datasource.libelle, type: dataSource.datasource.type, lastSyncDate: Math.max(maxDate, dataSource.datasource.lastSyncDate) }, headers: this.getHeaders() }); } else { return false; } }) .catch(err => { console.error('分块上传出错:', err); return false; });
核心逻辑说明:
- 两种方案都是串行执行:只有前一个分块上传完成并得到响应后,才会发起下一个请求,彻底避免了并发请求压垮服务器的问题。
- 保留了你原有的业务逻辑:所有分块上传成功后,才执行后续的
PUT请求;只要有一个分块失败,就返回false。 - 新增了错误捕获:任何一个分块上传失败都会进入
catch块,避免整个流程静默失败。
内容的提问来源于stack exchange,提问作者R0b0t0
相关产品推荐
相关产品推荐

