【问题标题】:how to discard initial data in a Firebase DB如何丢弃 Firebase 数据库中的初始数据
【发布时间】:2013-11-21 22:04:21
【问题描述】:

我正在制作一个简单的应用程序,通知客户其他客户点击了按钮。我将点击存储在 Firebase (db) 中,使用:

db.push({msg:data});

所有客户端都会通过on 收到其他用户点击的通知,例如

db.on('child_added',function(snapshot) { 
  var msg = snapshot.val().msg; 
});

但是,当页面首次加载时,我想丢弃堆栈上的所有现有数据。我的策略是在定义db.on('child_added',...) 之前调用db.once() 以获得初始子代数,然后使用它来丢弃对db.on('child_added',...) 的调用数。

不幸的是,所有对 db.on('child_added',...) 的调用都发生在之前我能够获得初始计数,所以它失败了。

我怎样才能有效而简单地丢弃初始数据?

【问题讨论】:

  • 因为这个问题的常见用例是创建一个消息队列,最好的答案是使用message queue strategy,在队列中添加和删除事件,而不用担心这种增加的复杂性.请在以下任何答案之前考虑该路线。

标签: firebase


【解决方案1】:

如果我正确理解您的问题,听起来您想要用户访问页面后添加的数据。在 Firebase 中,您描述的行为是设计使然,因为数据总是在变化,并且没有“旧”数据与“新”数据的概念。

但是,如果您只想显示页面加载后添加的数据,请尝试忽略之前的所有事件,直到整个子项集至少加载一次。例如:

var ignoreItems = true;
var ref = new Firebase('https://<your-Firebase>.firebaseio.com');
ref.on('child_added', function(snapshot) {
  if (!ignoreItems) {
    var msg = snapshot.val().msg;
    // do something here
  }
});
ref.once('value', function(snapshot) {
  ignoreItems = false;
});

此方法的替代方法是编写具有优先级的新项目,其中优先级为Firebase.ServerValue.TIMESTAMP(当前服务器时间),然后使用当前时间戳使用.startAt(...) 查询。但是,这比上述方法更复杂。

【讨论】:

  • 是的,这就是我要找的。我正在尝试一种变体,但我的更复杂。谢谢!
  • 此解决方案需要下载两次数据,这对于大型数据集来说并不理想。另外,如果数据集足够大,加载 value 需要很长时间,并且可能会丢失 child_add 中的某些项目。
  • 如果数据集足够大,确实会漏掉一些项目,但不会导致数据被下载两次。一般来说,如果只查询“自特定客户端上线以来的新项目”,最好根据时间戳查询数据,或者使用发布-订阅模型。
  • 是的,我做同样的事情。我做了一个聊天应用程序,并有一个 ChatManager 单例作为 firebase 事件的第一个处理程序,然后使用观察者设计模式通知其他侦听器。当 ChatManager 初始化时,我等待 4-5 秒再打开 should_handle_event 变量。在此之前发生的任何事件都将被丢弃。
【解决方案2】:

对于更大的数据集,Firebase 现在(从 2.0 开始)提供了一些可以简化此操作的查询方法。

如果我们在每条记录上添加一个时间戳字段,我们可以构造一个只查看新值的查询。考虑这个人为的数据:

{
  "messages": {
     "$messageid": {
        "sender": "kato",
        "message": "hello world"
        "created": 123456  // Firebase.ServerValue.TIMESTAMP
     }
  }
}

我们只能在“现在”之后找到消息:

var ref = new Firebase('https://<your instance>.firebaseio.com/messages');

var queryRef = ref.orderBy('created').startAt(Firebase.ServerValue.TIMESTAMP);

queryRef.on('child_added', function(snap) {
  console.log(snap.val());
});

【讨论】:

  • 如果我自己使用 REST API 创建一条新记录并将created 时间戳设置为我的服务器的时间戳,您将如何处理不一致?这当然也是 UTC,但您知道它可能与 Firebase 的时间不完全匹配
  • 使用 Firebase.ServerValue.TIMESTAMP 不会有任何不一致。如果您担心有人入侵您的软件以设置不一致的时间——他们一定很无聊——然后使用安全规则来强制时间戳的一致性。
  • 非常感谢,我又看了一遍,REST API 确实支持设置 Firebase 时间戳 '{".sv": "timestamp"}' firebase.com/docs/rest/api/#section-server-values
  • 你好 kato,你上面的例子不起作用,orderBy 不存在于 firebase 的 javascript 库中,仅存在于 REST API 中。此外,似乎无法将 firebase 时间戳(只是 json 对象)传递给 startAt,在示例文档中,startAt 仅采用整数。请参考我更新的问题stackoverflow.com/questions/30493719/…
  • 这个问题是一年多以前提出的。从那时起,API 发生了变化。请参阅queries 和任何 orderBy*() 方法。
猜你喜欢
  • 2020-01-12
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 2020-10-21
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多