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

使用Redux-Thunk/Redux-Firebase上传图片至Firebase Storage时Async/Await异常求助

问题分析与代码修正

我帮你看看问题出在哪哈~你遇到的result未等待Firebase返回URL的问题,核心是Async/await和Promise的使用细节没处理到位,主要有两个关键问题:

问题1:Promise未被正确返回给Promise.all

你在ads.image.map()的回调函数里创建了Promise,但没有return这个Promise!这就导致Promise.all实际接收的是一个充满undefined的数组,根本不会等待上传操作完成,自然result会立刻变成一堆undefined,等不到Firebase的返回结果。

问题2:数据整合逻辑错误

你在每个Promise内部都重新初始化了data = {...ads, imageUrl: []},这样每次循环都会生成一个新的对象,最后result里的每个元素都是只包含当前图片URL的独立对象,而不是把所有图片URL整合到同一个ads对象里,后续也没法直接用这个result发后端。


修正后的完整代码

export const postAds = (ads) => {
  return async (dispatch, getState, { getFirebase }) => {
    const firebase = getFirebase();
    try {
      // 先初始化基础数据,拷贝原ads内容并创建空的imageUrl数组
      const finalAdsData = { ...ads, imageUrl: [] };

      // 用Promise.all等待所有图片上传完成,注意map回调要return Promise
      const uploadedImages = await Promise.all(
        ads.image.map((imageItem) => {
          return new Promise((resolve, reject) => {
            const uploadTask = firebase
              .storage()
              .ref(`images/${imageItem.file.name}`)
              .put(imageItem.file);

            uploadTask.on(
              "state_changed",
              (snapshot) => {
                const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
                console.log(`图片 ${imageItem.file.name} 上传进度:${progress}%`);
              },
              // 上传失败时触发reject,同时dispatch错误action
              (err) => {
                dispatch({ type: "IMAGE_UPLOAD_ERROR", err });
                reject(err);
              },
              // 上传完成后获取下载URL
              () => {
                uploadTask.snapshot.ref
                  .getDownloadURL()
                  .then((downloadURL) => {
                    dispatch({ type: "IMAGE_UPLOAD_SUCCESS", payload: downloadURL });
                    // 只返回当前图片的URL和对应的alt,后续统一整合
                    resolve({ downloadURL, alt: imageItem.alt });
                  })
                  .catch(reject); // 捕获获取URL时的错误
              }
            );
          });
        })
      );

      // 把所有上传成功的图片URL和alt整合到finalAdsData里
      uploadedImages.forEach((img) => {
        finalAdsData.imageUrl.push(img);
      });

      console.log("所有图片上传完成,最终待发送数据:", finalAdsData);

      // 这里调用axios发送到后端,现在所有URL都已准备好
      // await axios.post("/your-backend-api-url", finalAdsData);

      // 可以dispatch一个广告发布成功的action
      // dispatch({ type: "POST_ADS_SUCCESS", payload: finalAdsData });

    } catch (err) {
      console.error("广告发布流程出错:", err);
      // dispatch({ type: "POST_ADS_ERROR", err });
    }
  };
};

关键修改说明

  1. 正确返回Promise:在ads.image.map()的回调里加上return new Promise(...),让Promise.all能正确收集所有上传任务的Promise,等待它们全部完成后再继续执行。
  2. 统一数据整合:把最终要发送的finalAdsData初始化放在循环外面,每个Promise只返回当前图片的URL和alt,等所有上传完成后,再把这些数据统一合并到finalAdsData的imageUrl数组里,保证数据结构正确。
  3. 完善错误处理:在上传错误回调里调用reject(err),同时捕获getDownloadURL的错误,确保任何一步出错都会被外层的try/catch捕获,避免流程卡死。
  4. 清晰的流程顺序:现在代码的逻辑是:初始化数据 → 等待所有图片上传并获取URL → 整合URL到数据 → 发送到后端,完全符合你需要的流程,不会再出现未等待的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 15:02:30