James Prado James Prado - 3 months ago 14
Javascript Question

Firebase, retrieving data asynchronously

I wrote a promise in javascript to delay an animation until some data is retrieved from my firebase database. The problem is that for some reason the promise isn't working, and the code isn't running asynchronously. Am i not using this promise properly, or is there another issue?

var name = document.querySelector('.name')

new Promise (function() {
firebase.database().ref('users/' + userId ).on('value', function(snap) {
console.log('first');
name.innerText = snap.child('name').val();
});
}).then(console.log('second'));


My issue is that when I check the console, I find that the code isn't running asynchronously, and I will see the messages logged in the wrong order, 'second' then 'first'.

Answer

The first problem is that (as I commented on cartant's answer) an on() handler can be invoked multiple times and this cannot be treated as a promise.

If you only care about the current value of the node, you can use once(), which does return a promise:

var name = document.querySelector('.name')

firebase.database().ref('users/' + userId ).once('value', function(snap) {
    console.log('first');   
    name.innerText = snap.child('name').val();
}).then(function() { console.log('second') });

Alternatively, if you do care about changes in the value too, you may want to keep on using on(). But in that case you should pass in a callback.

var name = document.querySelector('.name')

firebase.database().ref('users/' + userId ).on('value', function(snap) {
    console.log('first');   
    name.innerText = snap.child('name').val();
});

If you want to explicitly detect the first value in this, do something like:

var name = document.querySelector('.name'),
    isFirst = true;

firebase.database().ref('users/' + userId ).on('value', function(snap) {
    console.log('first');   
    name.innerText = snap.child('name').val();
    if (isFirst) {
        console.log('second');
    }
    isFirst = false;
});
Comments