【问题标题】:How do I do a nested database query within a for loop?如何在 for 循环中执行嵌套数据库查询?
【发布时间】:2017-11-15 10:12:18
【问题描述】:
supportChat: function(){
    return functions.https.onRequest((req, res) => {
        var userId = req.query.userId;
        var object = {};
        db.ref("/users/-KwZ2N38Q6a1a87p982/threads").orderByKey().once('value').then(function(snapshot) {
            var snap = snapshot.val();
            var keys = Object.keys(snap);

            for (var i = 0; i < keys.length; i++){
                k = keys[i];
                db.ref("/threads/"+k+"/lastMessage").orderByKey().once('value').then(function(snapshot){
                    var snapshot = snapshot.val();
                    if (snapshot[i]["sender"] != "-KwZ2N38Q6a1a87p982"){
                       object[snap[i]["messageID"]] = snapshot;
                    }
                });
            }
            console.log(object);
            return res.status(200).send(object);
        });
    });
},

我数据库中的每个用户都有一个线程子节点,它显示了他们正在进行的所有聊天线程。然后我们有数据库的另一个线程部分,其中包含该线程的所有数据。

我要做的是对照数据库的线程部分检查特定用户的线程 ID,以查找线程中最后一条消息不是由我(当前用户)发送的所有线程。

我不知道我为什么要为此苦苦挣扎。将满足我条件的每个线程的所有 snapshot.val() 一次性发送到端点的正确方法是什么?也许我的方法很遥远。

【问题讨论】:

    标签: javascript node.js firebase firebase-realtime-database google-cloud-functions


    【解决方案1】:

    要知道for 循环中的所有承诺何时完成,您可以累积从循环中获得的承诺数组,然后使用Promise.all() 知道它们何时全部完成。

    您还需要保护您的for 循环索引,以便for 循环的每次调用都维护自己的索引,以便在调用异步.then() 处理程序时它仍然正确。您可以通过将for 循环切换为使用let i 而不是var i 来做到这一点。

    supportChat: function(){
        return functions.https.onRequest((req, res) => {
            let userId = req.query.userId;
            let  object = {};
            db.ref("/users/-KwZ2N38Q6a1a87p982/threads").orderByKey().once('value').then(function(snapshot) {
                let snap = snapshot.val();
                let keys = Object.keys(snap);
                let promises = [];
    
                for (let i = 0; i < keys.length; i++){
                    let k = keys[i];
                    promises.push(db.ref("/threads/"+k+"/lastMessage").orderByKey().once('value').then(function(snapshot){
                        let snapshot = snapshot.val();
                        if (snapshot[i]["sender"] != "-KwZ2N38Q6a1a87p982"){
                           object[snap[i]["messageID"]] = snapshot;
                        }
                    }));
                }
                return Promise.all(promises).then(() => {
                    console.log(object);
                    return res.send(object);
                });
            }).catch(err => {
                console.log(err);
                return res.sendStatus(500);
            });
        });
    },
    

    代码上的其他cmets:

    仅供参考,如果您尝试从 supportChat() 函数实际返回某些内容,请指定它是什么。目前,尚不清楚您希望从该函数调用中返回什么。


    而且,您不需要 .status(200) 部分:

    res.status(200).send(object);
    

    你可以这样做:

    res.send(object);
    

    全部单独,将自动使用状态 200。


    而且,您需要一个.catch() 处理程序来捕获错误并在错误条件下发送响应。

    【讨论】:

    • 谢谢!看起来更健壮!我试过这个,但是当它运行时,它只返回一个消息对象(一个结果)。虽然有数百个。你认为哪里可能出错了?
    • @ryangineer - 你有没有像我展示的那样在for 循环中将var i 更改为let i?这是必需的,因此所有结果不使用相同的索引。
    • 对我做了一个小调整(小错字)。并明白了!这太棒了! thannnnkkk youuuuuuu。
    猜你喜欢
    • 1970-01-01
    • 2013-06-24
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    相关资源
    最近更新 更多