0

I've been banging my head against a wall the whole morning. I have the following code:

let fold = [{...},{...},{...}] // fold is an array of objects, abbreviated here for simplicity
let track = []
async function getTracks() {
   fold.forEach(async (f, index) => {
      let track = {};
      track.name = f.name;
      track.start = f.start;
      await storageRef
         .child(foldId + "/" + f.filename)
         .getDownloadURL()
         .then((url) => {
             console.log(url); // *
             track.src = url;
         });
      await tracks.push(track);
   });
}
getTracks().then(console.log(tracks)); // **

I expect to get an array of objects in track, which should be only printed to the console when the forEach loop finishes. Instead, I am getting the following output:

Array []
https://firebasestorage.googleapis.com/v0/b/musicfolds.appspot.com/o/L69IkyFyaLHu2KkxgrdL%2F1589059357106
https://firebasestorage.googleapis.com/v0/b/musicfolds.appspot.com/o/L69IkyFyaLHu2KkxgrdL%2F1589059425650
https://firebasestorage.googleapis.com/v0/b/musicfolds.appspot.com/o/L69IkyFyaLHu2KkxgrdL%2F1589553387295
https://firebasestorage.googleapis.com/v0/b/musicfolds.appspot.com/o/L69IkyFyaLHu2KkxgrdL%2F1589059596340
https://firebasestorage.googleapis.com/v0/b/musicfolds.appspot.com/o/L69IkyFyaLHu2KkxgrdL%2F1589570099464

As you see, the array is printed to the console from the .then instruction at ** before the forEach resolves the urls (which get printed in order at *, but after the .then! Incidentally, the array prints in a strange way: it appears empty, but when clicking on it (I'm on firefox in case that matters), it shows the results as expected.

How can I make my forEach loop wait until the urls return, so I can populate my array with actual values?

Thanks!!!

metronomme
  • 45
  • 6
  • 1
    `.forEach()` is not promise aware. Change to a regular `for` loop and then the `await` will actually pause the loop. Or, if you want to run in parallel, use `await Promise.all(fold.map(...))` and return a promise from within the `.map()` callback. – jfriend00 May 16 '20 at 16:02
  • Right, I knew there was something regarding that. Could you give me a simple example of returning a promise from within the `.map()` callback? Thanks! – metronomme May 16 '20 at 16:08
  • @metronomme "*returning a promise*" is just what your `async (f, index) => {` callback already does. – Bergi May 16 '20 at 16:12

0 Answers0