首页 文章

在从我的承诺/功能返回之前等待forEach完成

提问于
浏览
4

我正在使用Firebase Cloud Firestore,但是,我认为这可能更像是JavaScript异步vs同步承诺返回问题 .

我正在进行查询以从一个集合中获取ID,然后我循环查询该查询的结果,以根据该ID查找来自另一个集合的各个记录 .

然后我想将每个找到的记录存储到一个数组中,然后返回整个数组 .

results.length 始终为0,因为 return results 在forEach完成之前触发 . 如果我从forEach中打印 results.length 它有数据 .

在从外部promise和外部函数本身返回之前,我怎么能等到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);
            });
          }

2 回答

  • 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
    }
    
  • 2

    如果您有多个工作项同时执行来自循环,您可以收集所有工作项目中的所有承诺,并等待它们全部完成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
    })
    

    您可以根据自己的特定形式进行调整 .

相关问题