2017-12-01 9 views
0

Firebaseに格納された配列のトークンを返そうとしていますが、私は 'promise'を使用しています。'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; 
    } 

これは「ヘルパー」モジュールの「getToken」メソッドです。

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

問題は、配列が空になる)私がプッシュするたびにそれがすべて(正常に動作しますが、終了getUsersTokens配列にトークンということです。

ありがとうございました。

答えて

2

問題がhelper.getToken()はノンブロッキングなので、あなたのforEachtokensに自分のトークンを押して終了したgetToken()呼び出しのすべての前に実行が終了しますので、あなたのresult約束があまりにも早く解決されていることです。

少し簡単にするには、result約束を2つの約束事に分けることができます。最初の約束はsnapになります。第二約束は、トークンの配列を生成するためにsnapを反復を担当することになります。

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は約束の配列を取り込み、それらの約束もすべて解決されていたときに解決します。 getUsersTokenによって返される約束は、最終的にトークンの配列を含むことになる。promiseArrの各約束がトークンに解決されるからである。

1

これは、getToken()が解決する前にトークン配列で約束が解決されたためです。トークンが到着する前にハンドラが実行されるため、空の配列が表示されます。

解決するまで待つ必要があります。このように:@アンドレWerlangと@Christianサントスで指摘したように

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)); 
 
    }); 
 
    }); 
 
}

0

Promise.allそれはここで完璧な方法

function getUsersTokens() { 
let dbRef = db.ref('/system/users'); 
let result = new Promise((resolve, reject) => { 
    dbRef.once('value', (snap) => { 
     snap.reduce((chain, child) => { 
      return chain.then(array => { 
      return helper.getToken(child.key,db).then(function(token){ 
       return array.push(token); 
       }); 
      }); 
     }, Promise.resolve([])).then(tokens=>{ 
        resolve(tokens); 
       }); 
    }, (err) => { 
     reject(err); 
    }); 
}); 
return result; 
    } 
+0

それは動作しません削減使った例であります後でトークンが配列にプッシュされるためです。また、「Promise.resolve([])」は手間がかかり、約束を解決することは即時ではないという事実に依存しています。 –

関連する問題