我正在使用Firebase Cloud Firestore,但是,我认为这可能更像是JavaScript异步与同步承诺返回问题。
我正在进行查询以从一个集合中获取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);
});
}
答案 0 :(得分:6)
这里的诀窍是使用promises而不是结果填充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 :(得分: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
})
您可以根据自己的特定形式进行调整。