为什么我的Firebase'child_added'事件无序显示? [英] Why do my Firebase 'child_added' events show up out-of-order?

查看:124
本文介绍了为什么我的Firebase'child_added'事件无序显示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个限制查询在同一条路径。我加载一个限制(1),然后加载一个限制(50)。

当我加载第二个查询时,child_added事件don'按顺序点火。相反,列表中的最后一个项目(由limit(1)返回的项目)首先被触发,然后所有其他项目按顺序被触发,如下所示:

  **限制1:** 
新的Firebase(PATH).limit(1).on('child_added',...)
消息5

**限制2:**
新的Firebase(PATH).limit(50).on('child_added',...)
消息5
Message 1
Message 2
Message 3
Message 4

I在第二次限制操作中,为什么消息5被首先调用?为什么会发生这种情况,我该如何解决这个问题?解决方案

我知道这可能看起来很奇怪,但实际上这是预期的行为。

为了保证本地事件可以在不与服务器通信的情况下立即触发,Firebase不保证child_added事件总是按排序顺序调用。如果这是令人困惑的,可以这样想:如果你根本没有互联网连接,并且你设置了一个限制(50),然后调用push( )在那个参考文献上,你会期望一个事件立即被解雇。但是,如果重新连接到服务器,可能会发现服务器上的其他项目在您推送的服务器之前,然后会在添加的事件之后触发它们的事件。在你的例子中,这个问题与本地缓存的数据有关,而不是由本地客户端写入的数据,但是同样的原则适用。

更详细的客户端A调用push()和设置一些数据

  • 在线时,客户端B添加一个child_added的监听器来读取消息

  • 然后调用push()。它所推送的消息立即在本地触发一个child_added事件。

  • 客户端A重新联机。 Firebase会同步这些数据,而客户端B则会为该数据触发一个child_added事件。

    现在请注意,即使客户端A添加在列表中的第一个(因为它有一个较早的时间戳),事件被解雇第二。



    因此,您不能总是依赖事件顺序来反映Firebase子项的正确排序顺序。 b $ b

    但是别担心,你仍然可以得到你想要的行为!如果您希望数据按排序顺序显示,而不是事件到达客户端的顺序,您可以选择以下几种方式:

    1) (天真的做法)使用value事件而不是child_added,并在每次使用forEach触发时重绘整个项目列表。价值事件只对整套数据触发,因此每个事件总是按顺序枚举所有事件。但是,这种方法有两个缺点:(1)在从服务器加载初始状态之前,值事件不会触发,所以如果应用程序在离线模式下启动,直到网络连接可以成立。 (2)它无效地重绘每一个变化的一切。​​



    <更好的方法使用回调函数中的prevChildName参数on )。除了快照之外,当按照排序顺序排列项目时,on()的回调函数将传递查询中前一个子项的名称。这允许您以正确的顺序呈现孩子,即使事件按顺序发生。请参阅: https://www.firebase.com/docs/javascript/firebase/on.html

    我们的排行榜示例显示了一个方法来操纵DOM,以确保事物按正确的顺序呈现。请参阅:
    https://www.firebase.com/tutorial/#example/leaderboard


    I have 2 "limit" queries on the same path. I first load a "limit(1)", and then later load a "limit(50)".

    When I load the second query, the child_added events don't fire in-order. Instead, the last item in the list (the one returned by limit(1)) is fired first, and then all of the other items are fired in-order, like this:

    **Limit 1:**
    new Firebase(PATH).limit(1).on('child_added', ...) 
    Message 5  
    
    **Limit 2:**
    new Firebase(PATH).limit(50).on('child_added', ...) 
    Message 5 
    Message 1 
    Message 2 
    Message 3 
    Message 4 
    

    I'm confused why "Message 5" is being called first in the second limit operation. Why is this happening, and how can I fix it?

    解决方案

    I know this may seem strange, but this is actually the intended behavior.

    In order to guarantee that local events can fire immediately without communicating with the server first, Firebase makes no guarantees that child_added events will always be called in sort order.

    If this is confusing, think about it this way: If you had no internet connection at all, and you set up a limit(50), and then called push() on that reference, you would you expect an event to be fired immediately. When you reconnect to the server though, it may turn out that there were other items on the server before the one you pushed, which will then have their events triggered after the event for the one you added. In your example, the issue has to do with what data has been cached locally rather than something written by the local client, but the same principle applies.

    For a more detailed example of why things need to work this way, imagine 2 clients, A and B:

    1. While offline, Client A calls push() and sets some data
    2. While online, Client B adds a child_added listener to read the messages
    3. Client B then calls push(). The message it pushed triggers a child_added event right away locally.
    4. Client A comes back online. Firebase syncs the data, and client B gets a child_added event fired for that data.

    Now, note that even though the message Client A added comes first in the list (since it has an earlier timestamp), the event is fired second.

    So as you see, you can't always rely on the order of events to reflect the correct sort order of Firebase children.

    But don't worry, you can still get the behavior you want! If you want the data to show up in sort order rather than in the order the events arrived on your client, you have a couple of options:

    1) (The naive approach) Use a "value" event instead of child_added, and redraw the entire list of items every time it fires using forEach. Value events only ever fire for complete sets of data, so forEach will always enumerate all of the events in order. There's a couple of downsides to this approach though: (1) value events won't fire until initial state is loaded from the server, so it won't work if the app is started in "offline mode" until a network connection can be established. (2) It inefficiently redraws everything for every change.

    2) (The better approach) Use the prevChildName argument in the callback to on(). In addition to the snapshot, the callback for on() is passed the name of the previous child in in the query when items are placed in sort order. This allows you to render the children in the correct order, even if the events are fired out of order. See: https://www.firebase.com/docs/javascript/firebase/on.html

    Note that prevChildName only gives the previous child in the query, not in the whole Firebase location. So the child at the beginning of the query will have a prevChildName of null, even if there is a child on the server that comes before it.

    Our leaderboard example shows one way to manipulate the DOM to ensure things are rendered in the proper order. See: https://www.firebase.com/tutorial/#example/leaderboard

    这篇关于为什么我的Firebase'child_added'事件无序显示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆