【问题标题】:Why does the Firebase event 'child_added' fire after the 'value' event?为什么 Firebase 事件 'child_added' 在 'value' 事件之后触发?
【发布时间】:2015-11-10 07:00:17
【问题描述】:

根据 Firebase documentation

值事件总是最后触发,并保证包含在拍摄快照之前发生的任何其他事件的更新。

这是一个简单的示例 (jsbin),其中child_added 触发之前 value。使用当前最新的 Firebase 版本 (2.3.1) 确认了此行为:

var ref = new Firebase("https://reform.firebaseio.com");
ref.child('pets').once('value', function(snapshot) {

    snapshot.forEach(function(pet) {
        console.log("Pet: " + pet.key());

        pet.ref().child('food').once('value', function (foods) {
            console.log('value event called for ' + pet.key());
        });

        pet.ref().child('food').once('child_added', function (foods) {
            console.log('child_added event called for ' + pet.key());
        });
    });
});

在本例中,控制台日志为:

Pet: cat
Pet: dog
value event called for cat
child_added event called for cat
value event called for dog
child_added event called for dog

为什么child_added 事件在这种情况下最后触发?这不会违反文档中的保证吗?

【问题讨论】:

  • 使用 on() 而不是 once() 并且顺序会更有意义:jsbin.com/kuyida/edit?js,console
  • 我确认建议的更改更正了订单。您能否详细说明使用on 函数而不是once 时顺序正确的原因?这不违反规范,这似乎没有区分这两个功能吗?它只是说明事件的顺序是有保证的?我只是想知道这是否需要作为 Firebase 的错误提交。
  • 您附加了两个单独的侦听器,每个侦听器触发一个单独的请求,然后立即分离。通过对这些使用once(),您可以对事件进行排序。你可以不使用once()来解决这个问题。
  • 虽然使用on() 而不是once() 的建议更改解决了原始帖子中描述的事件顺序问题,但将另一个child_added 侦听器附加到顶级对象(“宠物” ) 导致附加到子属性的事件顺序再次不正确。这可以在这个修改后的示例中观察到:jsbin.com/selevo/edit?html,js,console。这似乎是另一个违反文档中“值事件总是最后触发[...]”保证的情况。在示例中添加最后一行代码后,有没有办法让顺序再次正确?
  • 只是用与 Firebase 支持人员交谈的结果/解决方案来更新这篇文章: (modified example) 中事件顺序颠倒的原因是(引用)“[我正在添加].. . 对现有数据的回调。添加回调时,客户端库会立即触发回调,而无需等待第二个注册,因为所有数据都可用。在示例中,可以通过反转添加回调的顺序来强制执行该顺序:jsbin.com/secuqo/1/edit?html,js,console

标签: javascript firebase


【解决方案1】:

总结来自 cmets 和 Firebase 支持的优秀反馈:

  1. 在这里使用on() 而不是once() 来注册事件监听器是最有意义的。在example of the original post,并引用 Firebase 支持:

    注册了 on() 回调,当注册了 once() 回调时,它是根据 on() 回调排序的。一旦触发了 once() 回调,它就会自动注销。即使事件的执行是按特定顺序完成的(由于 javascript 是单线程的),它们也是彼此分开计算的。

    Frank's correction to that example 展示了这一点。

  2. 修改后的示例再次打破了“保证”,因为(Firebase 支持):

    数据已经在客户端本地。因此,一旦您运行 ref.child('pets').on() 并发生回调,/pets 下的所有数据都已检索到客户端。现在在回调处理中,您正在向现有数据添加额外的回调。添加回调时,客户端库会立即触发回调,而无需等待注册第二个回调,因为所有数据都可用。

    由于我想在这种数据是本地的情况下强制执行保证,我只需在value 侦听器之前注册child_added 侦听器,如correction to the modified example 中所示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多