【问题标题】:Firebase child_added for new items onlyFirebase child_added 仅适用于新项目
【发布时间】:2017-09-12 10:43:59
【问题描述】:

我将 Firebase 和 Node 与 Redux 一起使用。我正在从一个键加载所有对象,如下所示。

firebaseDb.child('invites').on('child_added', snapshot => {
})

这种方法背后的想法是,我们从数据库中获取有效负载,并且只使用一个操作通过 Reducer 更新我的本地数据存储。

接下来,我需要监听密钥邀请的任何 NEWUPDATED 子级。 然而,现在的问题是 child_added 事件会触发所有现有键以及新添加的键。我不想要这种行为,我只需要新密钥,因为我已经检索了现有数据。

我知道 child_added 通常用于这种类型的操作,但是,我希望减少触发的操作数量,并因此触发渲染。

实现这一目标的最佳模式是什么?

谢谢,

【问题讨论】:

  • 只有当监听器第一次触发时,child_added 才会触发该节点子节点的数量,之后才会在添加新子节点时触发。
  • 我知道,这就是我在问题中提到的......我只想要新项目......

标签: javascript events firebase firebase-realtime-database redux


【解决方案1】:

虽然limit方法相当不错并且效率很高,但是你仍然需要在child_added中添加一个检查,最后一个要抓取的项目。另外我不知道是否仍然如此,但是您可能会从以前删除的项目中获得“旧”事件,因此您可能也需要注意这一点。

其他解决方案是:

使用布尔值防止旧添加的对象调用回调

let newItems = false

firebaseDb.child('invites').on('child_added', snapshot => {
  if (!newItems) { return }
  // do
})

firebaseDb.child('invites').once('value', () => {
  newItems = true
})

这种方法的缺点是它意味着如果你有一个很大的初始列表,它可能会导致什么都不做的事件可能会出现问题。

或者,如果您的邀请上有时间戳,请执行以下操作

firebaseDb.child('invites')
  .orderByChild('timestamp')
  .startAt(Date.now())
  .on('child_added', snapshot => {
  // do
})

【讨论】:

  • 在使用时间戳时不要忘记考虑服务器和客户端之间的时间差。查看文档中的Clock skew。检索到 serverTimeOffset 后,可以轻松添加它,例如 .startAt(Date.now() + serverTimeOffset)
【解决方案2】:

我已经使用以下方法解决了这个问题。

firebaseDb.child('invites').limitToLast(1).on('child_added', cb)
firebaseDb.child('invites').on('child_changed', cb)

limitToLast(1) 获取邀请的最后一个子对象,然后侦听任何新的子对象,将快照对象传递给 cb 回调。

child_changed 监听任何对邀请的子更新,将快照传递给 cb

【讨论】:

  • limitToLast(1) 承诺最后添加的项目正常。但是如果在您授权之前添加了超过 1 条记录会发生什么。除了最后一个,它会丢失它们。我认为错误的答案。对吗?
  • 这对我不起作用。添加的孩子不会触发任何事件。
【解决方案3】:

我通过忽略child_added 并仅使用child_changed 解决了这个问题。我这样做的方法是对我需要处理的任何项目执行update()将它们推送到数据库之后。此解决方案将取决于您的需求,但一个示例是在您希望触发事件时更新时间戳键。例如:

var newObj = { ... }
// push the new item with no events
fb.push(newObj)
// update a timestamp key on the item to trigger child_changed
fb.update({ updated: yourTimeStamp })

【讨论】:

    【解决方案4】:

    还有另一种解决方案: 获取孩子的数量并提取该值: 它正在工作。

    var ref = firebaseDb.child('invites')
    ref.once('value').then((dataSnapshot) => {
            return dataSnapshot.numChildren()
        }).then((count) =>{
            ref .on('child_added', (child) => {
                if(count>0){
                    count--
                    return
                }
                console.log("child really added")
              });
         });
    

    【讨论】:

      【解决方案5】:

      如果您的文档键是基于时间的(unix epoch、ISO8601 或 firebase 'push' 键),这种方法类似于 @balthazar 提出的第二种方法,对我们来说效果很好:

      const maxDataPoints = 100; 
      const ref = firebase.database().ref("someKey").orderByKey();
      // load the initial data, up to whatever max rows we want
      const initialData = await ref.limitToLast(maxDataPoints).once("value")
      // get the last key of the data we retrieved
      const lastDataPoint = initialDataTimebasedKeys.length > 0 ? initialDataTimebasedKeys[initialDataTimebasedKeys.length - 1].toString() : "0"
      // start listening for additions past this point...
      // this works because we're fetching ordered by key
      // and the key is timebased
      const subscriptionRef = ref.startAt(lastDataPoint + "0");
      const listener = subscriptionRef.on("child_added", async (snapshot) => {
          // do something here
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 2012-08-02
        • 2017-02-06
        • 1970-01-01
        • 2017-10-01
        相关资源
        最近更新 更多