0

I am trying to write a function that given a list of ids goes to firebase storage and retrieves the download URL for each id and saves the URLs in an array in the same order as the ids array. On testing I have found that the download URLs are returned in a random order. Below is some scaled down code of the aforementioned function.
1) Is there a way to cause the returned URLs to arrive in the correct order?
2) The setTimeout function is used after the loop to wait for 3 seconds otherwise the urlsToDownload array is empty. Is there a more accurate way to wait until all the URLs have been downloaded?

    function downloadAll() {
      var storageRef = firebase.storage().ref("/stuffToDownload");
      var urlsToDownload = [];
      var downloadIds = ['1', '2'];
      for (var x = 0; x < downloadIds.length; x++) {
          var downloadId = dowloadIds[x];
          (function(did) {
              var storageFileRef = storageRef.child(did);
              storageFileRef.getDownloadURL().then(function(url) {
                urlsToDownload.push(url);
              }).catch(function(error) {
                console.log("error");
              });
            })(downloadId);
          }
        }
      }
      setTimeout(function() {
        console.log("finished getting file urls", urlsToDownload.length);
        var index = 0;
        for(index = 0; index < urlsToDownload.length; index++){
          console.log(index + " " + urlsToDownload[index]);
        }
      }, 3000);
    }
KENdi
  • 7,576
  • 2
  • 16
  • 31
Simon Shaw
  • 175
  • 1
  • 10
  • 2
    That's because `storageFileRef.getDownloadURL()` is async. Your `for` loop fires all these requests at once. You need to wait for the response and only send the next request when the response of the previous one arrived. See also https://stackoverflow.com/questions/4288759/asynchronous-for-cycle-in-javascript – Günter Zöchbauer Oct 04 '17 at 11:02
  • 1
    Thanks, I used the reference to the other post in your response and that worked for me – Simon Shaw Oct 05 '17 at 22:02

1 Answers1

0

what you can do is wait for the URL to download then check the length of the urlsToDownload with the length of downloadIds, if matches call a function like below,

storageFileRef.getDownloadURL().then(function(url) {
            urlsToDownload.push(url);
            if(urlsToDownload.length==downloadIds.length){ //if you have all the files matching with downloadIds then you will get all the download URL
             _callConsoleLog()
            }
          })
var _callConsoleLog=function(){
    var index = 0;
    for(index = 0; index < urlsToDownload.length; index++){
      console.log(index + " " + urlsToDownload[index]);
    } 
}
MuruGan
  • 1,402
  • 2
  • 11
  • 23
  • This is a great solution that enables the setTimeout to be removed, however as far as I understand the order of the values in urlsToDownload will still be random – Simon Shaw Oct 05 '17 at 22:15
  • random means how? can you show with output, so I can help you – MuruGan Oct 06 '17 at 05:11