0

I have the following code which reads from an array of image URLs in imagesList, it then fetches from these images and adds them to the myDropzone1 box. The problem is that images are being added I think in the order they are done fetching, and not in the order they are listed in the array.

A possible solution I can think of is to use async/await, but I am not sure how to apply that to this bit of code. Please help.

for (var i = 0; i < imagesList.length; i++) {
   let name = imagesList[i];
   name = name.substring(name.lastIndexOf('/') + 1);

   fetch(imagesList[i])
       .then(res => res.blob())
       .then(blob => {
       let file = new File([blob], name, blob);
       myDropzone1.addFile(file);
   });
}

Thanks.

J K
  • 519
  • 5
  • 9
  • 28
  • There are several similar questions, this should be marked as duplicate. Check https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop – radar155 Mar 07 '19 at 12:28

2 Answers2

0

You are doing it right, and you don't really need async/await to fix this. You just have to make sure that you do not initiate the next call unless you do not have the response of the previous call.

You could achieve that with a recursive call, like this:

function fetchRecursively(imagesList, myDropzone1) {
  // execute only if there imageList has some value,
  if (imagesList.length) {
    let name = imagesList[0];
    name = name.substring(name.lastIndexOf('/') + 1);
    fetch(imagesList[0])
      .then(res => res.blob())
      .then(blob => {
        let file = new File([blob], name, blob);
        myDropzone1.addFile(file);

        // after a call has completed, shift the array and make next call.
        imagesList.shift();
        fetchRecursively(imagesList, myDropzone1);
     });
  }
  return;
}

Alternatively, you can use Promise.all to wait for all the fetch calls to complete and then execute your code [sequentially].

J K
  • 519
  • 5
  • 9
  • 28
Jayendra Sharan
  • 1,043
  • 6
  • 10
  • This is working I think. There are a couple of typos, imagesList instead of imageList, and I need to pass in myDropzone1 as a parameter to the function. I will need to give this a few more tests then will know if it works for sure. By the way, can we put some fail safe measure if one or more of the images failed to be fetched? Thanks. – J K Mar 07 '19 at 12:32
  • Hey, thanks for the edit. You can implement a failsafe like this, In the catch, extract the failed one, and then push back to the array (to retry, optional) and also maintain a list of failed ones, so that when next time it is tried again, and fails again, you'll know it has failed once, and then you can take a decision to either retry, or reject. – Jayendra Sharan Mar 07 '19 at 13:01
  • I am not very good in this. Can you please show me some codes how to do the failsafe? Thanks. – J K Mar 07 '19 at 14:57
0

I guess you could do this :

const fetchImages = async () => {
    for (let i = 0; i < imagesList.length; i++) {
        let name = imagesList[i];
        name = name.substring(name.lastIndexOf('/') + 1);

        let res = await fetch(imagesList[i]),
            blob = res.blob(),
            file = new File([blob], name, blob);

        myDropzone1.addFile(file);
    }
}

fetchImages();
Jeremy Thille
  • 26,047
  • 12
  • 43
  • 63
  • Tried the above code, the images are added but the actual images are not fetched successfully I think as the thumbnails in the myDropzone1 box appear to be blank. – J K Mar 07 '19 at 12:17
  • What does `console.log(imagesList[i])` say? – Jeremy Thille Mar 07 '19 at 12:19
  • console.log(imagesList[i]) lists image URLs correctly, for example: /images/Items/1903/08/file03511_3.jpg – J K Mar 07 '19 at 16:41