2017-12-10 10 views
2

私はFirebase Cloud Firestoreを使用していますが、これはもっとJavaScript非同期対同期の約束の返品の問題かもしれません。私の約束/機能から復帰する前にforEachが完了するのを待つ

私は1つのコレクションからIDを取得するためにクエリを実行しています。そのクエリの結果をループして、そのIDに基づいて別のコレクションの個々のレコードを参照しています。

次に、見つかった各レコードを配列に格納し、配列全体を返したいとします。

results.lengthは、forEachが完了する前にreturn resultsが発生するため、常に0です。私が内部でresults.lengthを印刷すると、それはデータを持っています。

外側の約束と外側の関数自体から戻る前にforEachが完了するまで、どうすればいいですか?

  getFacultyFavoritesFirebase() { 
      var dbRef = db.collection("users").doc(global.user_id).collection("favorites"); 
      var dbQuery = dbRef.where("type", "==", "faculty"); 
      var dbPromise = dbQuery.get(); 
      var results = []; 
      return dbPromise.then(function(querySnapshot) { 
       querySnapshot.forEach(function(doc) { 
        var docRef = db.collection("faculty").doc(doc.id); 
        docRef.get().then(function(doc) { 
        if (doc.exists) { 
         results.push(doc); 
        } 
        }) 
       }); 
       console.log(results.length); 
       return results; 
      }) 
      .catch(function(error) { 
       console.log("Error getting documents: ", error); 
      }); 
      } 
+0

プロミスの配列を1つの約束事にマージするには、「Promise.all」を使用できます。 – 4castle

答えて

5

ここでのトリックは、resultsに結果ではなく約束を設定することです。その後、約束の配列でPromise.all()に電話をかけ、あなたが望む結果を得ることができます。もちろん、doc.existsが約束を押す前に確認することはできませんので、一度Promise.all()を解決する必要があります。例:

function getFacultyFavoritesFirebase() { 
    var dbRef = db.collection("users").doc(global.user_id).collection("favorites"); 
    var dbQuery = dbRef.where("type", "==", "faculty"); 
    var dbPromise = dbQuery.get(); 
    // return the main promise 
    return dbPromise.then(function(querySnapshot) { 
     var results = []; 
     querySnapshot.forEach(function(doc) { 
      var docRef = db.collection("faculty").doc(doc.id); 
      // push promise from get into results 
      results.push(docRef.get()) 
     }); 
     // dbPromise.then() resolves to a single promise that resolves 
     // once all results have resolved 
     return Promise.all(results) 
    }) 
    .catch(function(error) { 
     console.log("Error getting documents: ", error); 
    }); 
} 

getFacultyFavoritesFirebase 
.then(results => { 
    // use results array here and check for .exists 
} 
1

することで、ループから来る同時に実行する作業の複数のアイテムを持っている場合は、すべての作業項目からのすべての約束を収集することができ、そしてそれらすべてがPromise.all()で終了するのを待ちます。可能なソリューションの一般的な形式は、次のようになります。

const promises = [] // collect all promises here 
items.forEach(item => { 
    const promise = item.doWork() 
    promises.push(promise) 
}) 
Promise.all(promises).then(results => { 
    // continue processing here 
    // results[0] is the result of the first promise in the promises array 
}) 

これは、独自の特定の形式に適したものに適合させることができます。

関連する問題