【问题标题】:Get only new "child added" after page load页面加载后仅获取新的“添加的子项”
【发布时间】:2015-06-08 08:09:21
【问题描述】:

我在网站右上角有 Facebook 样式通知。我在那里显示最多 5 条最新通知。我使用child_added 进行初始拉动,并在相同的firebaseRef child_added 监听新通知之后。

现在我想在新通知和少量新通知上播放声音。
我唯一想不通的是如何区分什么时候是新通知,什么时候已经看到,也就是页面重新加载?除了制作一些新财产read,还有其他方法吗?

我环顾四周,发现了一些 2012 年的旧答案,其中包含对我的情况没有帮助的建议 limitToLast(1)。

编辑:

https://stackoverflow.com/a/27693310/633154 这个@Kato 回答建议只收听时间超过当前 Firebase 时间Firebase.ServerValue.TIMESTAMP 的新通知。这似乎是要走的路,但我正在使用 REST API 创建一个新通知,并且我自己将时间戳设置为我的服务器的 UTC。所以可能会有一些细微的不一致。应该没什么大不了的

编辑 2:

通过此查询,我在页面加载时最多可以正确收到 5 个最新通知,之后不会再收到新通知

notifRef.limitToLast(5).once("value", function(snapshot) {
    snapshot.forEach(function(data) {
        addNotifications(data.val());
    });
});

在上面链接的其他 SO 线程中,@Kato 的答案不起作用,notifRef.orderBy is not a function
我根据文档尝试了多个其他版本
https://www.firebase.com/docs/web/guide/retrieving-data.html#section-queries

我的结构是一样的

{
  "messages": {
     "$messageid": { // firebase generated key 'JqcEWLFJrl1eaed5naN'
        "sender": "kato",
        "message": "hello world"
        "timestamp": 1433036536108  // Firebase.ServerValue.TIMESTAMP
     }
  }
}

这是我尝试做的以及我得到的错误:

var queryRef = notifRef.orderByKey().startAt(Firebase.ServerValue.TIMESTAMP);
错误:Query: When ordering by key, the argument passed to startAt(), endAt(),or equalTo() must be a string.

var queryRef = notifRef.orderByChild('timestamp').startAt(Firebase.ServerValue.TIMESTAMP);
错误:Query: First argument passed to startAt(), endAt(), or equalTo() cannot be an object.

在文档中,除了传递元素位置(整数)而不是 firebase 时间戳对象外,我还没有看到 startAt 的任何内容,这就是出现此类错误的原因。

只有下面的编译,只有 startAt 没有排序,但它没有发出任何新的通知!

var queryRef = notifRef.startAt(Firebase.ServerValue.TIMESTAMP);
queryRef.on('child_added', function(snap) {
    console.log(snap.val());
    addNotifications(snap.val());
    // TODO clean up if more than 5 notifications
});

知道问题出在哪里吗?只收听比当前时间戳更新的通知的正确方法是什么?

编辑 3

这是我的最终解决方案

notifRef.limitToLast(5).once("value", function(snapshot) {
    var lastKey = null; // at least 1 key is always present
    var count = 0; // because startAt is inclusive, we have to ignore first child_added
    snapshot.forEach(function(data) {
        addNotifications(data.val());
        lastKey = data.key();
    });
    checkNotifications();
    notifRef.orderByKey().startAt(lastKey).on('child_added', function(snap) {
        if (count > 0) {
            console.log(snap.val());
            addNotifications(snap.val());
            // TODO clean up if more than 5 notifications
            checkNotifications();
        }
        count++;
    });
});

我不信任浏览器时间,因此必须先查询最后 5 个现有密钥,然后将我收到的最后一个密钥传递给 startAtnotifRef.orderByKey().startAt(lastKey) 不能在 notifRef.limitToLast(5).once("value" 之外,因为根据文档,once 是最后查询的,因此传递给 startAtlastKey js 变量将始终为空。
还需要有count 变量,因为startAt 包含在内,但因为它已经存在,我需要忽略第一个。
当有超过 5 个通知时,也使用此解决方案,当使用 once 查询收到通知时,我只在最后使用 checkNotifications 查询我的后端一次。否则在 child_added 上,每次页面加载最多会执行 5 次。

如果有什么可以优化的,请告诉

【问题讨论】:

  • @FrankvanPuffelen 谢谢,看到了,但正如 some1 提到的那样,once('value' 效率不高,因为我可能有数百个通知,并且会拉出所有通知,但我最初只需要最多 5 个最新的然后只听新的
  • 最后一个代码 sn-p 不起作用,因为您还没有按时间戳排序。如果ref 指的是数据结构的根,则需要ref.child('messages').orderByChild('timestamp').startAt(Date.now()).once('child_added', function....。您希望将 Date.now() 替换为您上次检查的时间戳的位置。请注意,您的所有编辑和 cmets 都无助于使您的问题更清晰。如果您仍然遇到同样的问题,您通常会通过创建一个最小的小提琴来重现它并发布它来获得更好的响应。

标签: javascript firebase


【解决方案1】:

一种解决方案是让您的本地客户端通过ref.limitToLast(5).on('child_added', ...) 侦听最近的 5 个最新通知,然后仅在每个通知上的某些时间戳字段更新时才将它们呈现给用户您在机器上的本地时间戳。

当从其他客户端写入这些通知时,您可以包含一个通过Firebase.ServerValue.TIMESTAMP 指定的时间戳字段,它将使用服务器的 Unix 时间戳概念。然后,该数据的读取者可以将该时间戳与其本地时钟进行比较,以做出上述决定。

【讨论】:

  • 谢谢,这就是我目前拥有的notifRef.limitToLast(5).on("child_added", function(snapshot) { addNotifications(snapshot.val(), snapshot.key()); }); 这是触发每个页面加载,所以我会有另一个ref 只收听通知ref.orderBy('created').startAt(Firebase.ServerValue.TIMESTAMP); 就像@Kato 在另一个线程中回答(我的问题编辑中的链接)
  • 你好,还没有解决,请参考我在@Katos回答stackoverflow.com/a/27693310/633154987654321@的最后评论
  • 另外,我无法通过获取用户浏览器时间戳来获得您的解决方案,如果不是 UTC 并且在 Firebase 中,所有内容都存储为 UTC,我该如何依赖用户浏览器呢
  • @Skyzer new Date().getTime() 以与 Firebase.ServerValue.TIMESTAMP 相同的格式返回 UNIX 时间戳。
  • 谢谢你的兄弟,你和加藤的建议给我带来了正确的道路!我最后的编辑有我的最终方法。如果有什么可以优化的,可以建议
猜你喜欢
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多