0

I am trying to display data from my firebase database and images from firebase storage. Currently it seems to run some of my code before the other. I have shown my code below:

 <script>
            var wrapper = document.getElementById("myHTMLWrapper");
            var myHTML = '';
            var databaseRef = firebase.database().ref('items/');
            databaseRef.once('value', function(snapshot)
            {
              snapshot.forEach(function(childSnapshot) 
              {
                var childKey = childSnapshot.key;
                var childData = childSnapshot.val();
                myHTML += '<div class="card">';
                myHTML += '<div class="card-body">';
                var urlimage;
                storageRef.child('images/'+ childData.id +'.jpg').getDownloadURL().then(function(url){
                    urlimage = url;
                    console.log(urlimage);
                });
                console.log('url outside of function is: '+urlimage);
                myHTML += '<img src="'+ urlimage +'" class="img-thumbnail" height="">';
                console.log('images/'+ childData.id +'.jpg');
                myHTML += '<h4>'+ childData.sku + ' - ' + childData.name +'</h4>';
                myHTML += '</div>';
                myHTML += '</div>';
              });
              wrapper.innerHTML = myHTML;
            });
          </script>

It is returning the data from the database correctly but it is having issues resolving the URL of the image. From my console logs, the issue seems to be that the code is reaching console.log('url outside of function is: '+urlimage); before it reaches console.log(urlimage); even though it is above it in the code structure. I think it has something to do with how Javascript handles it. I would highly appreciate some help. Thanks in advance.

J W
  • 107
  • 1
  • 10

1 Answers1

1

it looks like "getDownloadURL" returns a Promise and you will get the url when that Promise is resolved so the behaviour you explained is normal. If you want to use the url value you have to move your code inside the callback function. something like this

var getURL = function(childSnapshot) {
   var childKey = childSnapshot.key;
   var childData = childSnapshot.val();
   return storageRef.child('images/'+ childData.id +'.jpg').getDownloadURL().then(function(url){
       var myHTML = '';
       myHTML += '<div class="card">';
       myHTML += '<div class="card-body">';
       myHTML += '<img src="'+ url +'" class="img-thumbnail" height="">';

       myHTML += '<h4>'+ childData.sku + ' - ' + childData.name +'</h4>';
       myHTML += '</div>';
       myHTML += '</div>';
       return myHTML;
  });
}
var promises = [];
snapshot.forEach(function(childSnapshot) {
       promises.push(getURL(childSnapshot));
}  
Promise.all(promises).then(results => {
     wrapper.innerHTML = results.join('');
}   
Reza Nasiri
  • 1,360
  • 1
  • 6
  • 19
  • Ah that makes sense. But I am having an issue where its just skipping over the callback function. Where myHTML just shows up blank. What do you think? Thanks. – J W Nov 25 '18 at 21:30
  • if the callback is not called, that means your Promise is rejected. I think it is because of the "." you have in your key(.jpg) but you can add a catch block to see exactly why it is rejected. – Reza Nasiri Nov 25 '18 at 21:38
  • I apologize for the confusion. What I meant was that it skipped it when it reached that part of the code. The promise eventually resolved but it was after the page already set the wrapper.innerHTML to an empty myHTML. – J W Nov 25 '18 at 21:41
  • You have to use Promise.all then. wait until all URLs are retrieved and then set the wrapper.innerHTML. – Reza Nasiri Nov 25 '18 at 21:50
  • Thank you again Reza. I am not too familiar with promise.all. Would you please kindly clarify? Thank you for your time and expertise. – J W Nov 25 '18 at 22:03
  • Updated the answer to reflect the change – Reza Nasiri Nov 25 '18 at 22:05
  • @RezaNasiri Don't forget to declare and initialise `myHTML` – Bergi Nov 25 '18 at 22:13
  • Wow. It works perfectly. Thank you so much for your guidance! I hope this will help people in the future. – J W Nov 25 '18 at 22:19
  • @RezaNasiri I added a few more items to the database and I am facing a small issue where each item is showing up multiple times. Is there something that is causing redundancy? – J W Nov 25 '18 at 22:40
  • make myHTML a local variable inside the callback function. – Reza Nasiri Nov 25 '18 at 22:56
  • Works like a charm. Thanks again @RezaNasiri – J W Nov 26 '18 at 05:50