You need to enable JavaScript to run this app. JavaScript循环内用async-await处理fetch 如何等待所有异步完成后执行富文本粘贴
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript循环内用async-await处理fetch 如何等待所有异步完成后执行富文本粘贴

问题根源

  • 现有循环逻辑属于无等待的异步触发流程:循环内调用的fetchBlob、fetchUrl是基于Promise的异步任务,但全程没有通过await阻塞等待执行结果,循环体不会卡在异步步骤上,会瞬间遍历完所有图片节点,直接执行后续的编辑器粘贴逻辑。
  • 所有网络请求都是后台并发发起,因此控制台会先打印全部loop end、execute html日志,等请求全部返回触发.then回调后,才会打印image日志。
  • 代码中存在几处冗余/错误:
    • 两个异步处理函数定义在循环内部,每遍历一个图片就重新声明一次,造成不必要的内存开销
    • fetchUrl内部已经通过response.json()将响应解析为JS对象,后续再调用JSON.parse(json)会抛出类型错误
    • 通过tmp.querySelectorAll('img')[i]回查DOM的方式容易因为索引错位(比如跳过无src的图片节点)匹配错元素

调整后的实现

优先推荐并发处理所有图片的方案(比逐张串行等待效率更高),核心逻辑是把每一张图片的处理任务封装成Promise收集成数组,通过Promise.all统一等待所有任务完成后,再执行编辑器粘贴动作。
调整后的完整代码如下:

// 通用工具函数移到循环外部统一声明,避免重复定义
async function fetchBlob(src) {
  const response = await fetch(src);
  if (!response.ok) throw new Error('图片源拉取失败');
  return response.blob();
}

async function uploadImage(file) {
  const formData = newTokenData();
  formData.append("image", file);
  const response = await fetch('upload-image', { 
    method: "POST", 
    body: formData 
  });
  // 直接返回解析后的JSON对象,无需后续二次parse
  return response.json();
}

const forLoop = async _ => {
  // 收集所有图片处理任务的Promise
  const imageTasks = [];

  for (let i = 0; i < imgNodeList.length; i++) {
    const img = imgNodeList[i];
    if (!img.src) continue;

    // 封装单张图片的全流程处理逻辑
    const singleTask = (async () => {
      try {
        // 1. 从源URL拉取图片Blob
        const blob = await fetchBlob(img.src);
        const file = new File([blob], "new_file");
        // 2. 上传图片到自有服务器
        const uploadRes = await uploadImage(file);
        console.log('image');
        
        // 3. 上传成功后替换临时DOM中的图片地址
        if (uploadRes.status == '200') {
          // 直接操作当前循环拿到的img对象,避免回查DOM导致索引错位
          img.src = uploadRes.url;
        }
      } catch (err) {
        // 单张图片处理失败不阻断整体流程,输出错误日志即可
        console.error('单张图片处理失败', err);
      }
    })();

    imageTasks.push(singleTask);
  }

  // 阻塞等待所有图片处理任务执行完成(包含成功、失败的所有状态)
  await Promise.all(imageTasks);

  // 所有图片地址替换完成后,再执行编辑器粘贴逻辑
  console.log('execute html');
  quill.clipboard.dangerouslyPasteHTML(index, tmp.innerHTML);
}
forLoop();

关键调整点说明

  • 移除了循环内无等待的.then链式调用,所有异步任务都被转化为可被等待的Promise对象
  • 通过await Promise.all(imageTasks)确保所有图片拉取、上传、DOM替换动作全部完成后,才会执行粘贴步骤,解决了先粘贴、后等图片上传的时序问题
  • 修复了原代码中重复声明函数、重复解析JSON、DOM查询索引错位的潜在bug
  • 增加单任务异常捕获,避免某一张图片处理失败导致整个流程无响应
  • 移除了原代码中冗余的isJson判断逻辑,因为response.json()本身会自动校验响应格式,解析失败会触发异常进入捕获逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 11:06:05