Firebase asyc/await 未从 foreach 循环返回完整结果

Firebase asyc/await not returning complete result from foreach loop

我正在努力让它正常工作。我的 nodejs 后端有这个功能

let data = [];
let lists = [];
var userId = request.params.userId;
var coll = db.collection("forms");
var query = coll.where("formUser", "==", userId);
await query.get().then(function (querySnapshot) {
    querySnapshot.forEach(function (doc) {
        var forms = doc.data();
        var listIDs = doc.data().formLists;

        listIDs.forEach(listId => {
            db.collection("lists").where("listId", "==", listId).get().then(function (snapshot) {
                snapshot.forEach(function (d) {
                    lists.push({ "id": d.data().listId, "text": d.data().listName });
                });
            });
        });
        forms.formLists = lists;
        data.push(forms);
    });
});

由于某种原因,第二个循环不只是工作,数据的结果来自第一个循环,如果我将相同的函数放在我的 javascript 前端中,我将获得带有 listID 的完整数据结果。

有什么想法吗?

添加单个await不会突然使它下面的所有代码运行同步。它通常也是一种将 awaitthen 组合在一起的反模式。我建议在您掌握异步行为之前远离 async / await,并在此之前坚持使用 then 并明确处理承诺。

如果您在 Cloud Functions 中共享的代码 运行,您将需要 return 一个承诺,在所有异步(读取和写入)操作完成后解析。因为你有很多这样的操作,你会想把你从他们那里得到的所有承诺捕获到一个数组中,然后使用 Promise.all() 作为 return 值:

var userId = request.params.userId;
var coll = db.collection("forms");
var query = coll.where("formUser", "==", userId);
return query.get().then(function (querySnapshot) { // 
    let promises = []; // 
    querySnapshot.forEach(function (doc) {
        var forms = doc.data();
        var listIDs = doc.data().formLists;

        listIDs.forEach(listId => {
            promises.push(db.collection("lists").where("listId", "==", listId).get()); // 
        });
    });
    return Promise.all(promises).then(function (snapshot) { // 
        return snapshot.map((d) => {
            return { "id": d.data().listId, "text": d.data().listName };
        });
    });
});

所以对于那些在如此复杂的数据结构中挣扎的人来说,这是我所做的:

        let data = [];
        let forms = [];
        let lists = [];
        var userId = request.params.userId;
        var coll = db.collection("forms");
        var query = coll.where("formUser", "==", userId);
        await query.get().then(function (querySnapshot) {
            querySnapshot.forEach(function (doc) {
                forms.push(doc.data());
            });
        });

        for (let index = 0; index < forms.length; index++) {
            const element = forms[index];
            var listIDs = element.formLists;
            for (const listId of listIDs) {
                await db.collection("lists").where("listId", "==", listId).get().then(function (snapshot) {
                    snapshot.forEach(function (d) {
                        lists.push({ "id": d.data().listId, "text": d.data().listName });
                    });
                });
            }
            element.formLists = lists;
            data.push(element);
        }
                            
        response.status(200).send(data); // pass your data to UI