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

JavaScript循环中如何等待多个Promise全部resolve后再执行后续逻辑

核心问题梳理

  1. Array.forEach没有返回值,方法直接返回forEach的执行结果相当于返回undefined,不符合返回Promise的类型要求,触发“并非所有代码路径都有返回值”的报错
  2. 混用Promise和Observable,异步流程没有统一管理,手动计数判断全部上传完成的方式容错性极低
  3. 嵌套层级过深,逻辑出现断层,内层的return无法透传到方法外层的调用方

修正后代码

import { firstValueFrom } from 'rxjs'; // rxjs 7+ 版本需要引入

// 可根据finilize的返回值调整Promise泛型,此处默认update返回Promise<void>
createSubmission(sub: Submission, files: Files[]): Promise<void> {
  // 把每个文件的上传、获取下载链接逻辑包装为独立Promise
  const uploadTasks = files.map(async file => {
    const storageRef = this.storage.ref(`files/${file.name}`);
    // 等待文件上传完成
    await storageRef.put(file);
    // Observable转Promise,rxjs 6及以下用.toPromise(),7+用firstValueFrom
    return firstValueFrom(storageRef.getDownloadURL());
  });

  // 等待所有文件任务全部执行完成,自动返回全量下载链接数组
  return Promise.all(uploadTasks).then(urlArray => {
    sub.filesUrls = urlArray;
    // 透传finilize的Promise,调用方可直接感知到最终提交完成状态
    return this.finilize(sub);
  });
}

finilize(sub: Submission): Promise<void> {
  const subRef = this.db.database.ref(`/submissions/${sub.medicUid}`).push(); 
  const subKey = subRef.getKey();
  sub.uid = subKey; 
  return subRef.update(sub);
}

关键修改说明

  • 用Array.map替代Array.forEach,收集所有文件的异步任务为Promise数组,保证方法的返回值始终是Promise类型
  • 用Promise.all统一管理所有异步任务,无需手动计数判断是否全部完成,天然支持任务失败时直接抛出异常,避免无意义的等待
  • 统一异步范式,将Observable类型的getDownloadURL()转为Promise,避免两种异步模式混用导致的流程失控
  • 直接透传最终的提交Promise,调用方可以直接通过await createSubmission()的方式等待整个流程执行完成

可选适配方案

如果需要容忍部分文件上传失败、仅提交上传成功的文件链接,可以把Promise.all替换为Promise.allSettled,自行过滤成功的返回结果即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 04:45:04