1

I have a Firebase database set up like this:

>>XXX
>>>>dislike: 0
>>>>like: 1

In my web application, I can retrieve their value into console by:

var fb = new Firebase('https://xxx.firebaseio.com');
fb.child('like').once('value',function(snapshot){
    console.log(snapshot.val());
});
fb.child('dislike').once('value',function(snapshot){
    console.log(snapshot.val());
});

Now if I want to retrieve these values into the global scope, it will return undefined when I do this:

var fb = new Firebase('https://xxx.firebaseio.com');
var like = fb.child('like').once('value',function(snapshot){
    return snapshot.val();
});
var dislike = fb.child('dislike').once('value',function(snapshot){
    return snapshot.val();
});

Of course I have a silly solution to this problem, by putting entire script inside these two scopes - but it would be a disasters if I have hundreds of scopes to work with, and if I like to dynamically turn them on and off. Here is my solution:

var likeRef = new Firebase('https://xxx.firebaseio.com/like');
var dislikeRef = new Firebase('https://xxx.firebaseio.com/dislike');
likeRef.once('value',function(likeObj){
  dislikeRef.once('value',function(dislikeObj){
    var like = likeObj.val();
    var dislike = dislikeObj.val();
  });
});

Here is another answer suggested by Frank van Puffelen from the source <Passing variable in parent scope to callback function>, and it didn't quite work because seem to only work for script that is adding a new object in an array. Here is my attempt:

var like = 0;
var dislike = 0;
var val = 0;
var fb = new Firebase('https://xxx.firebaseio.com/');

function fb_like() {
    fb.child('like').on('value', read_val);
    return val;
}
function fb_dislike() {
    fb.child('dislike').on('value', read_val);
    return val;
}
function read_val(snapshot) {
    var val = snapshot.val();
}

fb_like();
fb_dislike();

console.log(like);
console.log(dislike);

As you might expected, the console logs 0 and 0, instead of the values in like and dislike in firabase xxx database.

In fact, I took a step further and use array instead of integer value, and it still won't work:

var like = [0];
var dislike = [0];
var val = [0];
var fb = new Firebase('https://xxx.firebaseio.com/');

function fb_like() {
    fb.child('like').on('value', read_val);
    console.log('fb_like: ' + val[0]);
    return val;
}
function fb_dislike() {
    fb.child('dislike').on('value', read_val);
    console.log('fb_dislike: ' + val[0]);
    return val;
}
function read_val(snapshot) {
    val[0].value = snapshot.val();
}

fb_like();
fb_dislike();

console.log('Like: ' + like[0]);
console.log('Dislike: ' + dislike[0]);

The console will logs:

fb_like: 0
fb_dislike: 0
Like: 0
Dislike: 0

This means probably means only adding (pushing) new objects into an array will work on a global scope, changing the value of an object will only effect the local scope.

Then, I realized even adding (pushing) new objects into an array cannot effect the global scope. Here is my attempt:

var like = 0;
var likeObj = [];
var fb = new Firebase('https://xxx.firebaseio.com/');

function fb_like() {
    fb.child('like').on('value', read_like);
    console.log('fb_like: ' + likeObj[0]);
    return likeObj;
}
function read_like(snapshot) {
    likeObj.push(snapshot.val());
    console.log('likeObj: ' + likeObj[0]);
}

fb_like();
like = likeObj[0];

console.log('Like: ' + like);

As a result, the console logs:

fb_like: undefined
Like: undefined
likeObj: 1

This probably means the read_like() isn't effecting scopes larger than itself, event with array.push command.

Community
  • 1
  • 1
Aero Wang
  • 8,382
  • 14
  • 63
  • 99
  • Your return statement doesn't return from the once method. Read this answer for more information: http://stackoverflow.com/questions/27049342/asynchronous-access-to-an-array-in-firebase/27050749#27050749 or this one that doesn't use AngularFire: http://stackoverflow.com/questions/26297654/passing-variable-in-parent-scope-to-callback-function/26299662#26299662. – Frank van Puffelen Feb 25 '15 at 22:15
  • @FrankvanPuffelen Thanks! The second answer does seem to be work for adding a new object in an array. However, I like to change the value, and it failed. I updated my question. – Aero Wang Feb 26 '15 at 01:43
  • That last code fragment you added is pretty messy. For example: `read_val` doesn't return a value. But regardless of that: your `fb_like` and `fb_dislike` functions simply **cannot** return the value you're looking to return, since that value is loaded asynchronously. Which is exactly what the two answers I pointed two explain. If those answer are not enough, I'd recommend setting some breakpoints in your various functions. They won't be triggered in the order you expect, again: due to the asynchronous loading of data in Firebase (and most of the modern web). – Frank van Puffelen Feb 26 '15 at 02:53

0 Answers0