Emily
Emily

Reputation: 1151

How to make For loop wait for Firebase Database response?

I have a function that receives an object array. The array looks like this:

var receivedObjects = [{nuih329hs: 100}, {8suwhd73h: 500}, {2dsd73ud: 50}, {9u238ds: 200}];

Each key is an ID, and each value is a number. The objects are in a set order and what I want to do is iterate through the objects and define each value as a variable, which I'll then use when creating a html row.

The problem I'm having is, I have to make a call to a Firebase database inside this iteration code, the result is that while a row is successfully being created for each object value, the value entered into each row is always the same (the last/most recent value in the object array), so in the above case the number 200 is appearing in all four rows.

I think this might be happening because maybe all the iterations are completing before the first Firebase call is even completed, meaning the variable currentValue (which I'm entering into the rows) is set at the last value in the array before the first Firebase call is made.

Note: There is another array (called listOfIds) which contains Firebase IDs, I'm able to successfully use each ID from this array as a variable to use in the Firebase call, var currentID is that variable.

This is the function:

function populateTable(receivedObjects){

   var receivedObjectsLength = receivedObjects.length;
   // Note: an object array called listOfIds exists here (containing Firebase IDs to be used for querying Firebase), it's referenced below.

   for (var i = 0; i < receivedObjectsLength; i++) {

      // listOfIds is an Object array 
      var currentID = Object.keys(listOfIds[i]);

      var term = (Object.keys(receivedObjects[i])[0]);
      var currentValue = receivedObjects[i][term];

      //The following line is showing the correct ID and Value for each iteration:
      console.log("The current ID is: "+currentID+" and the current value is: "+currentValue);

      firebase.database().ref('/users/' + currentID).once('value').then(function(child) {

      // This is where the rows are created, ``currentValue`` is used here, but it's appearing as the same value in every row.

      // The next line is showing the correct current ID, but it's showing the currentValue as "200" in every row.
      console.log("The current ID is: "+currentID+" and the current value is: "+currentValue);

    });
  }
}

I'm very confused, because I thought the Javascript iteration code would wait until the data gets returned from the Firebase call, but it seems this isn't the case? How can I change my code so that the line console.log("The current ID is: "+currentID+" and the current value is: "+currentValue); inside the Firebase call success function will show the correct currentValue?

Upvotes: 1

Views: 3449

Answers (1)

FuzzyTree
FuzzyTree

Reputation: 32392

Instead of making the loop wait, you can use a function to put currentID and currentValue into their own scope so that they don't get overwritten with each iteration:

function getUser(currentID, currentValue) {
    return firebase.database().ref('/users/' + currentID).once('value').then(function(child) {
        console.log("The current ID is: "+currentID+" and the current value is: "+currentValue);
    });
}

In your loop:

for (var i = 0; i < receivedObjectsLength; i++) {
    ...
    getUser(currentID, currentValue)
}

Upvotes: 5

Related Questions