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

reduce中await未生效仅获单图,Promise.all报错的技术问题

异步reduce处理图片上传仅生成photo_0字段的问题解决

问题描述

我在数组的map方法中使用async函数,对每个对象的ImagesParagilder数组调用reduce结合await执行uploadImage图片上传操作,期望生成包含多张图片URL的对象,但最终仅得到photo_0字段;尝试用Promise.all包裹reduce时,出现TypeError: object is not iterable错误,不清楚为何console.log未等待reduce执行完成。

代码示例

foldersTreeImagesFiles.map( async (paragliderFolder) => {

        const pathfolder = pathImagesParaglider + '/' + paragliderFolder.subfolderName;
        const imagesUrl = await paragliderFolder.ImagesParagilder.reduce( async (UrlsImage, image, index) => {
            const pathImage = pathfolder + '/' + image;
            const folderCoulidinary = 'paraglider/' + paragliderFolder.subfolderName;

            const resu = await uploadImage(pathImage, folderCoulidinary);

            UrlsImage.name = paragliderFolder.subfolderName
            UrlsImage[`photo_${index}`] = resu;

            return UrlsImage

        }, {})

        console.log(imagesUrl);

    })

数组示例

[
  {
    subfolderName: 'Arcus_Rs',
    ImagesParagilder: [
      'swing_arcus2rs_slider_arcus6.jpg',
      'swing_arcus2rs_slider_arcus7.jpg',
      'swing_arcus2rs_slider_arcuslim4.jpg',
      'swing_arcus2rs_slider_arcuslime9.jpg'
    ],
    color: [
      'swing_arcus2rs_flame.png',
      'swing_arcus2rs_lime.png',
      'swing_arcus2rs_nightshade.png',
      'swing_arcus2rs_ocean.png'
    ]
  },
  {
    subfolderName: 'Coden_Pro',
    ImagesParagilder: [ 'DSC5495.jpg' ],
    color: [ 'Air.png', 'Earth.png', 'Fire.png', 'Water.png' ]
  },
  {
    subfolderName: 'Tonic_2',
    ImagesParagilder: [
      'DSC5349r.jpg',
      'DSC6647r.jpg',
      'P1044262r.jpg',
      'P1044438r.jpg',
      'P1044656r.jpg'
    ],
    color: [ 'Lind.png', 'Mustard.png' ]
  }
]

输出结果

{
  name: 'Arcus_Rs',
  photo_0: 'url********'
}
{
  name: 'Coden_Pro',
  photo_0: 'url********'
}
{
  name: 'Tonic_2',
  photo_0: 'url********'
}

问题原因

你在reduce里传入的是async函数,这个函数的返回值是Promise对象,而非你修改后的UrlsImage普通对象。第一次迭代后,下一次的UrlsImage参数变成了Promise,直接给Promise赋值name和photo_${index}不会生效,只有第一次迭代的photo_0被正确赋值,后续迭代都没作用到目标对象上。

另外,reduce本身不处理异步逻辑的链式等待,直接用await包裹整个reduce只能等最后一个Promise完成,但中间迭代已经因为参数是Promise而出错。

解决方法

方法一:在reduce中await前一次的Promise结果

每次迭代先await前一个reduce回调返回的Promise,拿到实际对象后再修改:

foldersTreeImagesFiles.map(async (paragliderFolder) => {
  const pathfolder = pathImagesParaglider + '/' + paragliderFolder.subfolderName;
  const imagesUrl = await paragliderFolder.ImagesParagilder.reduce(async (prevPromise, image, index) => {
    // 先拿到上一次迭代的实际对象
    const UrlsImage = await prevPromise;
    const pathImage = pathfolder + '/' + image;
    const folderCoulidinary = 'paraglider/' + paragliderFolder.subfolderName;

    const resu = await uploadImage(pathImage, folderCoulidinary);

    UrlsImage.name = paragliderFolder.subfolderName;
    UrlsImage[`photo_${index}`] = resu;

    return UrlsImage;
  }, Promise.resolve({})); // 初始值包装成Promise,统一类型

  console.log(imagesUrl);
});

方法二:用map+Promise.all代替reduce(更直观)

比起异步reduce,用map把每个图片转换成上传Promise,等全部完成后再组装成目标对象,逻辑更清晰:

foldersTreeImagesFiles.map(async (paragliderFolder) => {
  const pathfolder = pathImagesParaglider + '/' + paragliderFolder.subfolderName;
  const folderCoulidinary = 'paraglider/' + paragliderFolder.subfolderName;

  // 生成所有上传任务的Promise数组
  const uploadPromises = paragliderFolder.ImagesParagilder.map(async (image, index) => {
    const pathImage = pathfolder + '/' + image;
    const resu = await uploadImage(pathImage, folderCoulidinary);
    return { index, url: resu };
  });

  // 等待所有上传完成
  const results = await Promise.all(uploadPromises);

  // 组装成目标对象
  const imagesUrl = { name: paragliderFolder.subfolderName };
  results.forEach(({ index, url }) => {
    imagesUrl[`photo_${index}`] = url;
  });

  console.log(imagesUrl);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 06:35:16