本文介绍了在从我的承诺/函数返回之前等待 forEach 完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using Firebase Cloud Firestore, however, I think this may be more of a JavaScript asynchronous vs synchronous promise return issue.

我正在执行查询以从一个集合中获取 ID,然后我遍历该查询的结果以根据该 ID 从另一个集合中查找单个记录.

I am doing a query to get IDs from one collection, then I am looping over the results of that query to lookup individual records from another collection based on that ID.

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

Then I want to store each found record into an array and then return the entire array.

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

results.length is always 0 because return results fires before the forEach completes. If I print results.length from inside the forEach it has data.

如何才能等到 forEach 完成后再从外部承诺和外部函数本身返回?

How can I wait until the forEach is done before returning from the outer promise and the outer function itself?

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

推荐答案

这里的技巧是用承诺而不是结果填充 results.然后,您可以对该承诺数组调用 Promise.all() 并获得您想要的结果.当然,您无法在推送承诺之前检查 doc.exists 是否存在,因此您将需要在 Promise.all() 解析后进行处理.例如:

The trick here is to populate results with promises rather than the result. You can then call Promise.all() on that array of promises and get the results you want. Of course, you can't check if doc.exists before pushing the promise so you will need to deal with that once Promise.all() resolves. For example:

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
}

这篇关于在从我的承诺/函数返回之前等待 forEach 完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-28 04:11
查看更多