Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'promise' return empty array

I am trying to return Array of tokens stored in Firebase, and I am using 'promise'.

function getUsersTokens() {
 let dbRef = db.ref('/system/users');
 let result = new Promise((resolve, reject) => {
    dbRef.once('value', (snap) => {
        let tokens = [];
        snap.forEach(child => {
            if(child.Status != "occupied"){
                helper.getToken(child.key,db).then(function(token){
                    tokens.push(token);
                });
            }       
        }); 
        resolve(tokens);
    }, (err) => {
        reject(err);
    });
 });
 return result;
  }

and this is the 'getToken' method from the "helper" module.

exports.getToken=function(uid,db){
   return db.ref(`/Tokens/${uid}`).once('value').then(function(result){
     return result.val();
   });
};

The problem is that every time I push token into the array it all works fine, but when exit getUsersTokens() the array gets empty.

thanks for the help.

like image 999
m.d Avatar asked Oct 21 '25 00:10

m.d


2 Answers

The issue is that your result promise is resolving too early because the helper.getToken() is non-blocking, so your forEach will finish running before all of the getToken() calls have finished pushing their token into tokens.

To make things a little easier, you can split your result promise into two promises. The first promise will be in charge of getting snap. The second promise will be in charge of iterating through snap to produce an array of tokens:

function getUsersTokens() {

    let dbRef = db.ref('/system/users');

    let result = new Promise((resolve, reject) => {
        dbRef.once('value', (snap) => {
            resolve(snap);
        }, (err) => {
            reject(err);
        });
    });

    return result.then(snap => {

        let prommiseArr = [];

        snap.forEach(child => {
            if(child.Status != "occupied"){
                let p = helper.getToken(child.key,db);
                promiseArr.push(p);
            }  
        });

        return Promise.all(promiseArr); // resolves to array of tokens

    });
}

Promise.all takes in an array of promises, and resolves when all of those promises have also resolved. the promise returned by getUsersToken will ultimately contain an array of tokens, because each promise of promiseArr resolves to a token.

like image 55
Christian Santos Avatar answered Oct 23 '25 14:10

Christian Santos


It happens because the promise is resolved with the token array before getToken() resolves itself. You see an empty array because your handler runs before the tokens arrive.

You need to wait on that before resolving. Like this:

function getUsersTokens() {
  let dbRef = db.ref('/system/users');
  return new Promise((resolve, reject) => {
    dbRef.once('value', (snap) => {
      const tokensPromise = snap
        .filter(child => child.Status !== "occupied")
        .map(child => helper.getToken(child.key, db));
      resolve(Promise.all(tokensPromise));
    });
  });
}
like image 20
André Werlang Avatar answered Oct 23 '25 15:10

André Werlang



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!