You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:47:38