olivier
olivier

Reputation: 179

Await doesn't doing the job

I got this map function on a array:

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);

    })

The array exemple :

[
  {
    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' ]
  }
]

So i got this result :

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

i got only one photo, i should have more photo, so for me it the await of the reduce who doesn't work. If i try const imagesUrl = await Promies.all(paragliderFolder.ImagesParagilder.reduce( ect...)

i have a error: TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))

i don't understand why the console log doesn't wait the end of the reduce.

Upvotes: 1

Views: 89

Answers (2)

olivier
olivier

Reputation: 179

Hello after many research and trials here what i find.

the array.reduce() send only one promise so we can't use the Promise.all().

Here the trick to use a reduce with array of promise:

const array = [4, 7, 78];

const postsPromise = array.reduce((acc, element, index) => {
    return acc.then(async result => {
      const post = await fetch(`https://jsonplaceholder.typicode.com/posts/${element}`).then(res => res.json());
      return { ...result, [`Id_${index}`]: post.title };
    });
  }, Promise.resolve({}));

const posts = await postsPromise;
console.log(posts);

The Promise.resolve send a Promise already resolved and we loop over it

Upvotes: 0

Moritz Ringler
Moritz Ringler

Reputation: 15796

When you do await in your reducer, the function immediately returns a Promise and quits. At the second iteration, UrlsImage is actually the Promise from the first iteration, not the object you put into the reducer. I think this is not what you want.

Try something like this:

const promises = paragliderFolder.ImagesParagilder.map( async (image, index) => {
  const pathImage = pathfolder + '/' + image;
  const folderCoulidinary = 'paraglider/' + paragliderFolder.subfolderName;

  const resu = await uploadImage(pathImage, folderCoulidinary);
  return [`photo_${index}`, resu]
})
const entries = await Promise.all(promises)
const imagesUrl = Object.fromEntries(entries)

This will load each image and give you a tuple from which you can build what I assume you want imagesUrl to look like. Not sure about the name property, it seems like you wanted to override it in every iteration.

Here is a dummy-application using it:

function uploadImage(pathImage, folderCoulidinary){
  return new Promise((resolve) => {
    resolve('uploaded to:' + pathImage)
  })
}

const paragliderFolder = {
  ImagesParagilder: [
    'img1', 'img2'
  ]
}
const pathfolder = 'pathfolder'

async function runit(){
  const promises = paragliderFolder.ImagesParagilder.map( async (image, index) => {
    const pathImage = pathfolder + '/' + image;
    const folderCoulidinary = 'paraglider/' + paragliderFolder.subfolderName;

    const resu = await uploadImage(pathImage, folderCoulidinary);
    return [`photo_${index}`, resu]
  })
  const entries = await Promise.all(promises)
  return Object.fromEntries(entries)
}

runit().then(o => console.log(o))

Upvotes: 2

Related Questions