0

I am trying to get the promise returned from another function. Here is my code:

function getData(){
var result = [];
return new Promise(function(resolve){
var query = firebase.database().ref('groups');
query.once('value').then(data => {
    data.forEach(snapshot => {

        var gdata = snapshot.val();
        var grp = snapshot.key;
        result.push(grp);
    });
});
resolve(result);
});
}

I managed to print out the data for 'grp' variable from the function above. In my second fuction where I tried to access the data returned from promise:

However, from the second function, when I tried to print out in the .then(), nothing is actually printed out. Why is it so?

Thanks!

4 Answers4

1

First, firebase already returns a Promise, so there's no need to create a new one. You should put the data into result and return the promise directly.

function getData() {
    var query = firebase.database().ref('groups');
    return query.once('value').then(data => {
        let res = [];
        data.forEach(snapshot => {
            var gdata = snapshot.val();
            var grp = snapshot.key;
            res.push(grp);
        });
        return res;
    });
}

You can then simply chain that

function plotData() {
    return getData().then(data => {
        data.forEach(console.log);
    });
}
baao
  • 71,625
  • 17
  • 143
  • 203
0

You resolve the promise too early. But don't create new promises if you don't need to:

function getData(){
  var result = [];
  var query = firebase.database().ref('groups');
  return query.once('value').then(data => {
    return data.map(snapshot => snapshot.key);
  });
}
PeterMader
  • 6,987
  • 1
  • 21
  • 31
0

The bad news: If you need to use a .then() function to get the value you want (as with your firebase method) then you have to return a promise from your function. This is the case even for your inner function.

The good news is that .then() can be used to "convert" the return value of a function; and will even unravel returned promises for you (if, say, you decide you need to perform a second database call before you have your answer)

function getData(){
    var query = firebase.database().ref('groups');
    return query.once('value').then(data => {
        var result = [];
        data.forEach(snapshot => {

            var gdata = snapshot.val();
            var grp = snapshot.key;
            result.push(grp);
        });
        return result;
    });
    resolve(result);
}

Take note how I return result inside of the .then() function. Since I'm returning the result of .then(), this will then evaluate to a promise that, rather than purely returning data, will return result.

I'm less certain what you're doing with the second block. You shouldn't need the Promise.all or map around getData unless you actually intend to call it multiple times; and given that your list is empty, it seems like it's not called at all.

DISCLAIMER: I know the promises concept well, but not firebase. If firebase has unique aspects to it that change how this should work, I may be wrong.

Katana314
  • 8,429
  • 2
  • 28
  • 36
  • I am trying to access whatever is returned from the getData() in the second block. How can I access the returned value in this case? –  Aug 22 '17 at 13:23
  • Should be just `getData().then(list => { ...`. Promises have complicated constructors, but anytime you're writing code around the ones being returned to you, even when making new ones, it can often be pretty short. – Katana314 Aug 22 '17 at 13:26
  • Hey sorry but just a quick check with you, let's say when I try to access the data returned in .then(), for each of them, I am passing as parameter to another function. For example, for each groups, I am passing the group as parameter to getMember(group). Then inside getMember(), I am performing the same thing to fetch data and return to plotData(). However, with the nested .then(), it is broken now. –  Aug 22 '17 at 13:39
  • @guest176969 That does sound more complicated and maybe expands past your question. However, it also sounds a bit like that could make use of that "Unraveled promises" idea I mentioned in my answer. `plotData` would, again, *have* to return a promise. If you return one call to `getMember()` inside `then`, the result will be `getMember`'s result (not just the promise made by `getMember`). Then you would have to expand that to use Promise.all and return all getMember calls. I'd encourage you to experiment to get a better idea of it. The resulting code should not be *very* long. – Katana314 Aug 22 '17 at 13:46
-1

list.map() does not resolve, it is not a promise... Promise.all needs to receive a promise.

You probably wanted to invoke getData() there.

Rastko
  • 477
  • 2
  • 7