【问题标题】:Firebase child_added only get child addedFirebase child_added 只添加孩子
【发布时间】:2012-08-01 02:23:28
【问题描述】:

来自 Firebase API:

添加了孩子:每个初始孩子都会触发一次此事件 在这个位置,每次新的时候都会再次触发 添加了孩子。

一些代码:

listRef.on('child_added', function(childSnapshot, prevChildName) {
    // do something with the child
});

但是由于该位置的每个孩子都会调用一次该函数,有没有办法只获取实际添加的孩子?

【问题讨论】:

  • 为什么这个方法不按照它说的去做呢?它应该只做一件事——添加孩子时触发——仅此而已。
  • 是的,同意@jose Browne。它令人困惑......

标签: firebase


【解决方案1】:

要跟踪自某个检查点以来添加的内容而不获取以前的记录,您可以使用endAt()limit() 获取最后一条记录:

// retrieve the last record from `ref`
ref.endAt().limitToLast(1).on('child_added', function(snapshot) {

   // all records after the last continue to invoke this function
   console.log(snapshot.name(), snapshot.val());

});

【讨论】:

  • 实际上,我发现了一种更简单的方法,因为即使在达到 limit() 之后,它也会继续通知您添加的事件。我已经相应地更新了我的答案。
  • 不清楚你的意思。这仅适用于有序集,但如果您需要订购其他东西(除了有序集?)...此外,您的评论无助于任何人了解如何在 Firebase 中获取子添加事件。
  • 回调函数只对ref.endAt().limit(1)返回的记录触发一次。它不会为在该记录之后添加的其他新记录触发。我正在使用 Angularfire 0.8.0 进行测试
  • 加藤在 GitHub 上有很好的解释,here
  • 那仍然会为最后一个孩子调用一次回调(在添加新孩子之前),对吧?
【解决方案2】:

limit() 方法已弃用。 limitToLast()limitToFirst() 方法替换它。

// retrieve the last record from `ref`
ref.limitToLast(1).on('child_added', function(snapshot) {

   // all records after the last continue to invoke this function
   console.log(snapshot.name(), snapshot.val());
   // get the last inserted key
   console.log(snapshot.key());

});

【讨论】:

  • 我已经尝试过这种方法,但有一点需要注意:如果最后一条记录被删除,例如用户发表评论并立即将其删除(例如这是一个错误)上面的 .on() 函数将被再次调用。我解决了添加时间戳并检查添加的孩子是否小于一秒,如果它更旧,它是一个旧记录并且没有被添加。为此,请查看 ref.child('.info')
  • 我不明白 - 这不只是得到最后一个项目吗?那么“仅绑定到此事件后添加的项目”呢?
  • 是的,我也想知道。它只获取最后一项,然后不会触发其他添加的事件。
  • @DivZero 我试着照你说的做,但由于我的聊天是在 android 和 iOS 之间共享的,所以它不起作用,因为来自其他设备的消息延迟更长。这也容易出错,所以我检查了新消息是否已经在聊天中,如果是我不添加它。
  • child_added 函数采用两个参数,snapshotprevChildKey,这种方法 prevChildKey 始终为空。我用ref.endAt().on('child_added', function(snapshot, prev) {});
【解决方案3】:

由于在没有数据的情况下调用ref.push()方法会根据时间生成路径键,所以我就是这样做的:

// Get your base reference
const messagesRef = firebase.database().ref().child("messages");

// Get a firebase generated key, based on current time
const startKey = messagesRef.push().key;

// 'startAt' this key, equivalent to 'start from the present second'
messagesRef.orderByKey().startAt(startKey)
.on("child_added", 
    (snapshot)=>{ /*Do something with future children*/}
);

请注意,ref.push() 返回的引用(或“键”)实际上没有写入任何内容,因此无需捕获空数据。

【讨论】:

    【解决方案4】:

    我尝试了其他答案方式,但至少为最后一个孩子调用了一次。如果您的数据中有时间键,则可以这样做。

    ref.orderByChild('createdAt').startAt(Date.now()).on('child_added', ...
    

    【讨论】:

    • [2018-04-27T23:58:32.727Z] @firebase/database:FIREBASE 警告:使用未指定的索引。您的数据将在客户端下载和过滤。考虑将 /sms-log 中的 ".indexOn": "createdAt" 添加到您的安全规则中以获得更好的性能。
    【解决方案5】:

    Swift3 解决方案:

    您可以通过以下代码检索您之前的数据:

    queryRef?.observeSingleEvent(of: .value, with: { (snapshot) in
        //Your code
    })
    

    然后通过以下代码观察新数据。

    queryRef?.queryLimited(toLast: 1).observe(.childAdded, with: { (snapshot) in
        //Your Code
    })
    

    【讨论】:

    • 您能否对此进行扩展,以便 .childAdded 不会添加所有消息。所以,如果我使用一个数组,我想在 observeSingleEvent 查询最后 100 个,然后在 .chlidAdded 和 .childRemoved 监听所有新事件。
    • 如果我正确理解你的问题,你想在开始时检索最后 100 条记录,然后你想收听更新。根据 Google 文档,您可以在这件事上使用“queryLimitedToLast”观察者。 firebase.google.com/docs/database/ios/lists-of-data
    猜你喜欢
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 2015-01-07
    相关资源
    最近更新 更多