我有一个应用程序,每隔 5 秒左右就会将新的孩子添加到 Firebase。我有成千上万的孩子。
在应用程序加载时,我想以不同的方式处理最初的数千个与每 5 秒滴流的后续子级。
您可能会建议我使用 value,处理所有内容,然后使用 children_added。但我相信如果处理时间太长,我可能会错过任何一点。
有没有办法在 Firebase 中做到这一点,保证我不会错过任何一点?
我有一个应用程序,每隔 5 秒左右就会将新的孩子添加到 Firebase。我有成千上万的孩子。
在应用程序加载时,我想以不同的方式处理最初的数千个与每 5 秒滴流的后续子级。
您可能会建议我使用 value,处理所有内容,然后使用 children_added。但我相信如果处理时间太长,我可能会错过任何一点。
有没有办法在 Firebase 中做到这一点,保证我不会错过任何一点?
由于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_added
和value
listener 只会下载一次数据。为已经通过网络的数据添加新的 Firebase 侦听器非常便宜,您应该对定期执行此类操作感到自在。
如果您担心在实际不需要时下载所有初始数据,我会按照评论中@FrankvanPuffelen 的建议使用带时间戳的查询。这非常有效,并且使用 Firebase 查询进行了优化。
在数据库中添加了 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);
});
改进了@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
});
});
这个问题有两种可能的解决方案,都不令人满意:
1)时间戳你的孩子,只请求时间戳大于“现在”值的孩子。这不是很好,因为您的应用程序的“现在”和“现在”之间可能存在同步问题,因为无论是将数据推送到 Firebase 或“现在”的 Firebase 服务器值。
2)使用价值和添加的孩子。在 child_add 中看到的任何已在 value 中看到的重复项都可能被丢弃。这对于大型数据集是不可用的,因为它需要两次下载所有历史数据!
为什么不能有一个像“child_added”这样的命令,它永远不会给出所有的东西?