为啥我的 Firebase 'child_added' 事件出现乱序?

Posted

技术标签:

【中文标题】为啥我的 Firebase \'child_added\' 事件出现乱序?【英文标题】:Why do my Firebase 'child_added' events show up out-of-order?为什么我的 Firebase 'child_added' 事件出现乱序? 【发布时间】:2013-03-30 20:43:06 【问题描述】:

我在同一路径上有 2 个“限制”查询。我先加载一个“limit(1)”,然后再加载一个“limit(50)”。

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

**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 

我很困惑为什么在第二个限制操作中首先调用“消息 5”。为什么会发生这种情况,我该如何解决?

【问题讨论】:

【参考方案1】:

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

为了保证本地事件可以在不首先与服务器通信的情况下立即触发,Firebase 不保证始终按排序顺序调用 child_added 事件。

如果这令人困惑,请这样想:如果您根本没有互联网连接,并且您设置了一个限制 (50),然后在该引用上调用 push(),您会期望一个事件立即被解雇。但是,当您重新连接到服务器时,可能会发现服务器上在您推送的项目之前还有其他项目,然后将在您添加的事件之后触发它们的事件。在您的示例中,问题与本地缓存的数据有关,而不是本地客户端写入的数据,但同样的原则也适用。

有关为什么事情需要以这种方式工作的更详细示例,请想象 2 个客户,A 和 B:

    离线时,客户端 A 调用 push() 并设置一些数据 在线时,客户端 B 添加一个 child_added 监听器来读取消息 客户端 B 然后调用 push()。它推送的消息会立即在本地触发 child_added 事件。 客户端 A 重新联机。 Firebase 同步数据,客户端 B 会为该数据触发 child_added 事件。

现在,请注意,即使客户端 A 添加的消息在列表中排在第一位(因为它具有较早的时间戳),事件也会在第二个触发。

如您所见,您不能总是依靠事件顺序来反映 Firebase 子项的正确排序顺序。

不过不用担心,你仍然可以获得你想要的行为!如果您希望数据按排序顺序显示,而不是按事件到达客户端的顺序显示,您有两种选择:

1) (天真的方法) 使用“value”事件而不是 child_added,并在每次使用 forEach 触发时重新绘制整个项目列表。值事件只会触发完整的数据集,因此 forEach 将始终按顺序枚举所有事件。但是这种方法有几个缺点:(1) 值事件在从服务器加载初始状态之前不会触发,因此如果应用程序在“离线模式”下启动,直到可以建立网络连接,它才会起作用已确立的。 (2) 每次更改都会重新绘制所有内容,效率低下。

2) (更好的方法) 在 on() 的回调中使用 prevChildName 参数。除了快照之外,当项目按排序顺序放置时,on() 的回调会在查询中传递上一个子项的名称。这允许您以正确的顺序呈现子级,即使事件被无序触发。见:https://www.firebase.com/docs/javascript/firebase/on.html

请注意,prevChildName 仅提供查询中的前一个子项,而不是整个 Firebase 位置。因此,查询开头的子节点的 prevChildName 将为 null,即使在它之前的服务器上有一个子节点。

我们的排行榜示例展示了一种操纵 DOM 以确保事物以正确顺序呈现的方法。看: https://www.firebase.com/tutorial/#example/leaderboard

【讨论】:

现在已经过时了吗?文档说“从 Firebase 读取有序数据很简单,因为排序是自动完成的。您的 child_added / child_moved / child_changed 事件将以正确的顺序调用。” firebase.com/docs/ordered-data.html 这里也一样,我想即使对于离线场景,价值事件也可以。此外,对于带有 shouldComponentUpdate 检查的 React 来说,低效的重绘不是问题。

以上是关于为啥我的 Firebase 'child_added' 事件出现乱序?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 firebase 监听器重复记录

为啥我的 Firebase 存储 URL 没有上传到 Google Cloud Firestore?

为啥 Firebase 功能部署非常缓慢?

为啥我的应用程序在尝试登录时崩溃(firebase 登录)

为啥我没有在我的 react 应用程序中获取 firebase 存储文件 url?

为啥重新安装我的 iOS 应用后 Firebase Messaging 无法正常工作?