为什么我的Firebase查询返回错误的顺序?

为什么我的Firebase查询返回错误的顺序?,firebase,Firebase,背景 大家好,我正在Firebase中执行一个查询,检索消息列表: ref.child("messages").on("child_added", function(snapshot) { console.log(snapshot.val()); }); 上面的查询工作正常。它按顺序显示消息 消息包含以下属性/字段: <message-id>: { user-id: <user-id>, message: "This is a sample m

背景

大家好,我正在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
}   
问题是内部查询返回的消息列表顺序错误。为什么?为了以正确的顺序显示信息,正确的方式应该是什么

编辑

好的,给你。以下是导出的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按您期望的顺序检索消息。您可以通过添加一些附加日志来轻松验证这一点:

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"
在前三行中,您看到的是消息是有序的。但是您随后开始检索每个消息的用户;而且这些用户不一定会按照您解雇/期望的顺序返回

在web上使用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)操作,因此不能很好地随用户数扩展


repo:

“错误的顺序”是非常主观的,在您向我们展示您的数据样本和您预期的顺序之前是不可更改的。请参阅,无论何时下载用户快照,都会调用第二个回调。一个可能在较早开始的下载之前完成下载。您无法控制该异步回调的顺序。@AnidMonsur好的,那么根据用户id检索用户名的正确方法是什么?@FrankvanPuffelen我包含了消息列表的屏幕截图。您正在以正确的方法检索它。问题在于回调结构。你的目标是什么?当然,您要做的不仅仅是console.log。我们需要看到更多信息才能提供一个好的答案。我如何才能做到这一点:
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;
    });
});