37

我有一个应用程序,每隔 5 秒左右就会将新的孩子添加到 Firebase。我有成千上万的孩子。

在应用程序加载时,我想以不同的方式处理最初的数千个与每 5 秒滴流的后续子级。

您可能会建议我使用 value,处理所有内容,然后使用 children_added。但我相信如果处理时间太长,我可能会错过任何一点。

有没有办法在 Firebase 中做到这一点,保证我不会错过任何一点?

4

4 回答 4

69

由于child_added初始预加载数据的事件将在父事件触发之前value触发,因此您可以将该value事件用作一种“初始数据加载”通知。这是我从另一个类似的 StackOverflow 问题中稍微修改的一些代码。

var initialDataLoaded = false;
var ref = new Firebase('https://<your-Firebase>.firebaseio.com');

ref.on('child_added', function(snapshot) {
  if (initialDataLoaded) {
    var msg = snapshot.val().msg;
    // do something here
  } else {
    // we are ignoring this child since it is pre-existing data
  }
});

ref.once('value', function(snapshot) {
  initialDataLoaded = true;
});

值得庆幸的是,Firebase 会巧妙地缓存这些数据,这意味着创建 achild_addedvaluelistener 只会下载一次数据。为已经通过网络的数据添加新的 Firebase 侦听器非常便宜,您应该对定期执行此类操作感到自在。

如果您担心在实际不需要时下载所有初始数据,我会按照评论中@FrankvanPuffelen 的建议使用带时间戳的查询。这非常有效,并且使用 Firebase 查询进行了优化。

于 2015-01-17T02:35:31.027 回答
2

在数据库中添加了 createdAt 时间戳并将 child_add 限制为当前时间,这对我来说似乎工作正常。

const onChildAdded = database()
  .ref(refURL)
  .limitToLast(constValues.LAST_MESSAGE_ADDED)
  .orderByChild('createdAt')
  .startAt(date.getTime())
  .on('child_added', (snapshot) => {
    parseMessage(snapshot);
  });

database()
  .ref(refURL)
  .limitToLast(constValues.LAST_MESSAGES_LIMIT)
  .once('value', (snapshot) => {
    parseInitialMessages(snapshot);
    setLoading(false);
  });
于 2020-08-18T08:49:57.270 回答
-1

改进了@jacobawenger 的答案以不使用全局状态变量

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

ref.once('value', function(snapshot) {
  // do something here with initial value

  ref.on('child_added', function(snapshot) {
    // do something here with added childs
  });

});
于 2016-06-14T11:51:43.110 回答
-2

这个问题有两种可能的解决方案,都不令人满意:

1)时间戳你的孩子,只请求时间戳大于“现在”值的孩子。这不是很好,因为您的应用程序的“现在”和“现在”之间可能存在同步问题,因为无论是将数据推送到 Firebase 或“现在”的 Firebase 服务器值。

2)使用价值和添加的孩子。在 child_add 中看到的任何已在 value 中看到的重复项都可能被丢弃。这对于大型数据集是不可用的,因为它需要两次下载所有历史数据!

为什么不能有一个像“child_added”这样的命令,它永远不会给出所有的东西?

于 2015-01-16T16:30:49.213 回答