Asynchronous access to an array in Firebase
Welcome to Asynchronous Loading 101.
var userTokens = userTokenSync.$asArray();
console.log(userTokens);
console.log(userTokens[0]);
for(var i=0, len = userTokens.length; i < len; i++) {
console.log(userTokens[i]);
}
console.log('done');
The first line of this snippets starts loading your data from Firebase. But that loading might take some time. And since the browser doesn't want to block things, it continues executing the script.
By the time the browser executes your console.log(userTokens);
the data most likely hasn't been loaded yet. So it just prints the object to the console as a placeholder.
By the time it gets to the for
loop, the data may or may not yet have been loaded from Firebase.
At some point you clicked the arrow next to the logged userTokens
. By that time the data had loaded from Firebase and the console shows the latest data.
The solution is provided by AngularFire, in the form of a promise. AngularFire promises to at some point in the future have the data for you. If you have a piece of code that should only execute when the data is loaded, you can write it like this:
var userTokens = userTokenSync.$asArray();
console.log(userTokens);
console.log(userTokens[0]);
userTokens.$loaded(function(userTokens) {
for(var i=0, len = userTokens.length; i < len; i++) {
console.log(userTokens[i]);
}
console.log('done');
});
console.log('at last line, but not done yet');
Update
Note that the above is a bad example of when to use $loaded
. Since $loaded
will fire only once, it will only log the initial contents of the array. If you're just trying to see if/when your data has loaded, the idiomatic approach is to add the userTokens
to the scope:
$scope.userTokens = userTokens;
And add this to your view/HTML:
<pre>{{ userTokens | json }}</pre>
AngularFire will now monitor when the userTokens are loaded or modified in any way and will tell AngularJS to update the view if that happens.
Also see these:
- Firebase, AngularJS and GeoFire - wait for response from factory
- Firebase angularfire child.$asObject give properties undefined
- angularfire - why can't I loop over array returned by $asArray?
- Passing variable in parent scope to callback function
- Trying to get child records from Firebase
Yup... we get this question a lot.