【问题标题】:Why does my Firebase query return the wrong order?为什么我的 Firebase 查询返回错误的顺序?
【发布时间】:2015-11-03 10:59:35
【问题描述】:

背景

大家好,我正在 Firebase 中执行一个检索消息列表的查询:

ref.child("messages").on("child_added", function(snapshot) {
    console.log(snapshot.val());
});

上述查询工作正常。它按顺序显示消息。

一条消息包含以下属性/字段:

<message-id>: { 
    user-id: <user-id>,
    message: "This is a sample message",
    time: 1446534920014
}   

问题

显示消息时,我还需要显示用户名。所以我需要添加另一个使用user-id 字段检索用户名的查询:

ref.child("messages").on("child_added", function(snapshot) {
    var message = snapshot.val();
            
    // get the user's name
    ref.child("users").child(message["user-id"]).once("value", function(userSnapshot) {
        // logs the results in the wrong order
        console.log(message, userSnapshot.val().name);
    }
});

问题是内部查询以错误的顺序返回消息列表。为什么?为了以正确的顺序显示消息,正确的方法应该是什么?

编辑

好的,给你。下面是导出的 JSON:

{
  "messages" : {
    "-K2FyInlsZqLdHou1QnA" : {
      "message" : "Message 1",
      "user-id" : "-K2Fxr1gdxynukjDzcIq"
    },
    "-K2FyOlw13MU9KHB5NQh" : {
      "message" : "Message 2",
      "user-id" : "-K2Fxr1gdxynukjDzcIq"
    },
    "-K2Fz2GxPgqGf8uDfK0d" : {
      "message" : "Message 3",
      "user-id" : "-K2Fy3uyw-RNcePo_Pn-"
    }
  },
  "users" : {
    "-K2Fxr1gdxynukjDzcIq" : {
      "name" : "John Joe"
    },
    "-K2Fy3uyw-RNcePo_Pn-" : {
      "name" : "Alfred"
    }
  }
}

我的目标只是显示消息(按顺序)以及用户名。如果我这样做:

ref.child("messages").on("child_added", function(snapshot) {
    console.log(snapshot.val());
});

它按顺序显示消息,即消息 1、消息 2、消息 3。但我仍然没有用户名,所以我需要查看用户列表以在显示消息之前检索用户名:

ref.child("messages").on("child_added", function(snapshot) {
    ref.child("users").child(snapshot.val()["user-id"]).once("value", function(userSnapshot) {
        console.log(snapshot.val(), userSnapshot.val().name);
    });
});

返回包含用户名的消息列表,但问题是它的顺序错误:消息 2、消息 1、消息 3

【问题讨论】:

  • “错误的顺序”是高度主观的并且无法修复,除非您向我们展示您的数据样本和您期望的顺序。请参阅stackoverflow.com/help/mcve
  • 每当下载用户快照时都会调用第二个回调。一个可能在较早开始的一个之前完成下载。您无法控制该异步回调的顺序。
  • @AnidMonsur 好的,那么根据用户 ID 检索用户名的正确方法是什么?
  • @FrankvanPuffelen 我附上了邮件列表的截图。
  • 您正在以正确的方式检索它。问题是您的回调结构。你的目标是什么?当然,您想做的不仅仅是 console.log。我们需要看到更多才能提供一个好的答案。

标签: firebase


【解决方案1】:

消息按您期望的顺序检索。您可以通过添加一些额外的日志记录轻松验证这一点:

ref.child("messages").on("child_added", function(snapshot) {
    var message = snapshot.val();
    console.log(message.message);

    ref.child("users").child(message["user-id"]).once("value", function(userSnapshot) {
        console.log(message.message+': '+userSnapshot.val().name);
    });
});

我最近运行的输出是:

"Message 1"
"Message 2"
"Message 3"
"Message 2: John Joe"
"Message 1: John Joe"
"Message 3: Alfred"

您在前三行中看到的是消息是按顺序排列的。但是您随后开始为每条消息检索用户;并且这些用户不一定会按照您解雇/预期他们的顺序回来。

这是在网络上使用 AJAX 时非常常见的问题:一旦涉及到网络流量,您的代码顺序不一定是事情发生的顺序。

解决方案总是相同的:不要依赖于您的代码以特定顺序执行。例如:您很可能希望在 DOM 中某处的列表中显示消息。

var ul = document.getElementById('messages');
ref.child("messages").on("child_added", function(snapshot) {
    var message = snapshot.val();
    var li = document.createElement('li');
    li.id = 'msg_'+snapshot.key();
    li.innerText = message.message;
    ul.appendChild(li);

    ref.child("users").child(message["user-id"]).once("value", function(userSnapshot) {
        li.innerText = userSnapshot.val().name + ': '+ li.innerText;
    });
});    

旁注:您可能需要考虑添加用户名缓存。您现在将为每个用户、每个用户调用数据库。这是一个 O(n^2) 操作,因此不能很好地随用户数量扩展。

复制:http://jsbin.com/zofasi/edit?js,console

【讨论】:

猜你喜欢
  • 2012-07-05
  • 2015-11-26
  • 2014-01-26
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
  • 2019-12-25
  • 2015-03-04
相关资源
最近更新 更多