Reputation: 4555
I am trying to retrieve data from my database. My code creates an empty array and appends a child to it each time one is added. It then creates the list (ignore the MDL classes) and adds it to the HTML document.
<script>
// get emergencies to array
var firebaseRef = firebase.database().ref('Incidents');
var emergencies = [];
// var emergencies = ['Test', 'Test 2', 'Test 3'];
firebaseRef.on('child_added', function(snap) {
snap.forEach(function (childSnap) {
console.log(childSnap.val());
emergencies.push(childSnap.val());
});
});
var opentag = '<ul class="mdl-list" id="emergenciesList">',
closetag = '</ul>',
array = [];
for (i = 1; i <= emergencies.length; i++) {
array[i] = '<li class="mdl-list__item">' + emergencies[i] + '</li>';
}
var newArray = array.join(" ");
document.getElementById('foo').innerHTML = opentag + newArray + closetag;
</script>
The weird thing is, that at the console.log() statement, the data is retrieved perfectly fine, but after the string manipulation, newArray is undefined. Help!
Upvotes: 0
Views: 551
Reputation: 598728
The problem is caused by the way you've ordered your code. The order in which the lines are executed are not what you think. It's easiest to see this if you reduce it to this:
var firebaseRef = firebase.database().ref('Incidents');
console.log("Before database loading started");
firebaseRef.on('child_added', function(snap) {
console.log("In child_added");
});
console.log("After database loading started");
Now the order in which the logging will be written is:
Before database loading started
After database loading started
In child_added
This is probably not what you expected. The reason the logging shows in this order is that Firebase loads the data asynchronously. So while the on('child_added'
lines starts loading the data, it may take some time to get that data from the Firebase servers. Instead of waiting for the data (which would block the ability of your users to interact with your app), the browser continues to execute the statements after the block. Then when the data is available, it calls your callback function.
A common way of dealing with the asynchronicity is by reframing your problems. Right now your code is written as "first load the data, then add it to the HTML". Try instead framing it as "start loading the data. When the data is available, add it to the HTML". That translates into this code:
var firebaseRef = firebase.database().ref('Incidents');
firebaseRef.on('child_added', function(snapshot) {
var ul = document.getElementById("emergenciesList");
if (!ul) {
document.getElementById('foo').innerHTML = '<ul class="mdl-list" id="emergenciesList"></ul>';
ul = document.getElementById("emergenciesList");
}
var li = document.createElement("li");
li.classList.append("mdl-list__item"); // or: li.className = "mdl-list__item"
li.id = snapshot.key;
li.innerText = snapshot.val();
ul.appendChild(li);
});
I removed the loop over the snapshot, because I'm not sure it is needed and it complicates the code. If your data structure needs the loop, you can add it back where it was.
Upvotes: 1