1

I tried to get the data from Firebase and store it into an array. However, when I try to get the data from the array, it became undefined. Can anyone tell me why would it happened?

var events = [];
var databaseRef = database.ref("events").orderByChild("date");

databaseRef.on('child_added', function(snapshot) {
  var event = snapshot.val(); 

  events.push({
    title: event.title, 
    content: event.content
  });
});

console.log(events);
console.log(events[0]);
console.log(events.pop());

In #1, all the data is stored as object in the array. But in #2&3, it returns undefined

add: #1 returns:

[]
    0 : Object
        content : "Rehoncus. Aliquam nibh antegestas id dictum a, commodo. Praesenterto faucibus malesuada faucibu"
        title : "Tivamus at magna non nunc"
    1 : Object
        content : "Rehoncus. Aliquam nibh antegestas id dictum a, commodo. Praesenterto faucibus malesuada faucibu"
        title : "Vivamus at magna non nunc"
lawchihon
  • 13
  • 1
  • 7
  • The reason that the content of the events array appears to be written to the console is because when an array is expanded in the developer tools console, the current array content is shown. Note that `[]` - an empty array - is what's shown in the console before you expand it. – cartant Aug 25 '16 at 21:56

2 Answers2

4

Your data is loaded from Firebase asynchronously. By the time your console.log statements execute, the data hasn't come back from the Firebase servers yet. This is easiest to see by adding a few extra log statements:

var events = [];
var databaseRef = database.ref("events").orderByChild("date");

console.log("before attaching listener");
databaseRef.on('child_added', function(snapshot) {
  console.log("in listener callback");
});
console.log("after attaching listener");

The order of the log statements will be:

before attaching listener

after attaching listener

in listener callback

in listener callback

in listener callback

This is probably not what you expected. But it is very common when programming against cloud-based services, such as the Firebase Database. In fact: with Firebase Database this is the only way to handle continuous synchronization of data. If somebody adds a new event tomorrow, you will get another:

in listener callback

To deal with this asynchronous loading, you typically have to invert your way of thinking. The usual way that we deal with code is sequently: first I will load the data, then I will do something with that data. With Firebase, you need to think reactively: whenever I get data, I will do something with it.

Say you want to add an element to the HTML for each event and update an average event duration. You can do this by:

var events = [];
var databaseRef = database.ref("events").orderByChild("date");

databaseRef.on('child_added', function(snapshot) {
  var event = snapshot.val(); 

  // add the event to the UI
  var elm = document.createElement('li');
  elm.id = 'event-'+snapshot.key;
  elm.innerText = event.title;
  document.querySelector('#event-list').appendChild(elm);

  // add the event to our list
  events.push({
    title: event.title, 
    content: event.content
  });

  // update/recalculate our avg event duration
  calculateAverageEventDuration(events);
});
Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
0

Try:

console.log(JSON.stringify(events[0]));

Depeding on your data, you can try JSON.parse too to manage the elements. It should helps.

Airton Barbosa
  • 121
  • 1
  • 7