1

I am trying to return 3 promises from my firebase DB and once all three promises have been fulfilled I basically want to render a new page or do whatever. So I do a Promise.All(...) but my lists are still empty afterwards.

My queries are correct because when I console.log() within each of those functions, I get the objects returned from my DB but my Promise.All isn't waiting for those promises to resolve and instead executes the code within the Promise.All which is returning empty lists.

app.get('...', function (req, res) {
  //Return first promise from DB save to zone_obj list
  var zone_key = req.params.id;
  var zone_obj = [];
  firebase.database().ref(...).once('value').then((snapme) => {
    zone_obj.push(snapme.val());
  });
  
  //Return second promise from DB save to members list
  var members = [];
  firebase.database().ref(...).on("value", function (snapshott) {
    snapshott.forEach((snapper) => {
      members.push(snapper.val());
    });
  });
  
  //Return third promise from DB save to experiences list
  var experiences = [];
  firebase.database().ref(...).on("value", function (snapshot) {
    snapshot.forEach((snap) => {
      firebase.database().ref(...).once("value").then((snapit) => {
        experiences.push(snapit);
      });
    });
   });
   
  //once all promises have resolved
  Promise.all([experiences,zone_obj,members]).then(values => {
    console.log(values[0]); //returns []
    console.log(values[1]); //returns []
    console.log(values[2]); //returns []
  });
});
KENdi
  • 7,576
  • 2
  • 16
  • 31
user3892254
  • 139
  • 2
  • 15
  • callback to `on('value',` ... is asynchronous - you're executing promise.all before any `on('value'` could possibly be "fired" – Jaromanda X Feb 08 '18 at 10:27
  • also, your array in Promise.all is an array of (empty due to above issue) arrays, could never be an array of promises – Jaromanda X Feb 08 '18 at 10:30

1 Answers1

2

This is not actually firebase's problem. Firebase method .on("value") is actually a listener that will be bound to firebase to get real-time updates and that is not actually a promise and your callback function will be called every time when data on that node is changed. so if you want to save or get data only once use firebase.database().ref(...).set() and firebase.database().ref(...).once() method respectively.

According to firebase docs

On method

on(eventType, callback, cancelCallbackOrContext, context) returns function()

once method

once(eventType, successCallback, failureCallbackOrContext, context) returns firebase.Promise containing any type

So change your code to following

app.get('...', function (req, res) {
    var promises = []

    //Return first promise from DB save to zone_obj list
    promises.push(firebase.database().ref(...).once('value'));

    //Return second promise from DB save to members list
    promises.push(firebase.database().ref(...).once('value'));

    //Return third promise from DB save to experiences list
    promises.push(firebase.database().ref(...).once('value'));

    //once all promises have resolved
    Promise.all(promises).then(values => {
        console.log(values[0]); // zone_obj 
        console.log(values[1]); // members 
        console.log(values[2]); // experiences 
    });
});
Ridham Tarpara
  • 5,970
  • 4
  • 19
  • 39