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

循环分片上传场景下await与.then的使用差异及实现方案

解决方案

核心思路

要实现循环内分片按顺序上传的.then()写法,本质是利用Promise链式调用的串行执行特性:我们维护一个初始为已完成状态的Promise根节点,每一轮循环都把当前分片的上传逻辑挂载到上一个Promise的.then()回调中,确保前一个分片上传完成后才会触发下一个分片的上传任务。

完整改写代码

const fileReader = new FileReader();
const theFile = f.files[0];
fileReader.onload = (ev) => {
  const CHUNK_SIZE = 5000;
  const chunkCount = ev.target.result.byteLength / CHUNK_SIZE;
  console.log("Read successfully");
  const fileName = Math.random() * 1000 + theFile.name;
  // 初始化Promise链的起点,初始状态为已完成
  let uploadChain = Promise.resolve();
  for (let chunkId = 0; chunkId < chunkCount + 1; chunkId++) {
    // 把当前分片任务追加到链上
    uploadChain = uploadChain.then(() => {
      const chunk = ev.target.result.slice(
        chunkId * CHUNK_SIZE,
        chunkId * CHUNK_SIZE + CHUNK_SIZE
      );
      // 返回fetch的Promise,让链式调用等待当前上传完成
      return fetch("http://localhost:8080/upload", {
        method: "POST",
        headers: {
          "content-type": "application/octet-stream",
          "content-length": chunk.length,
          "file-name": fileName,
        },
        body: chunk,
      }).then(() => {
        // 上传完成后更新进度,对应原来await之后的逻辑
        divOutput.textContent = Math.round((chunkId * 100) / chunkCount, 0) + "%";
      });
    });
  }
  // 所有分片上传完成后的回调,对应原来循环结束后的逻辑
  uploadChain.then(() => {
    console.log(ev.target.result.byteLength);
  });
};
fileReader.readAsArrayBuffer(theFile);

注意要点

  • 循环中使用let声明chunkId,利用块级作用域特性保证每个分片回调里拿到的分片ID正确,避免异步回调变量污染问题
  • 每个.then()回调必须返回当前fetch产生的Promise,否则链式调用不会等待上传完成就会执行下一个任务,导致分片顺序混乱
  • 所有分片全部上传完成后的逻辑可以挂载到最终的uploadChain的.then()回调中执行

内容的提问来源于stack exchange,提问作者Vehbi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:48:05