我有一个应用程序,每5秒左右就会有新的孩子被添加到Firebase。我有成千上万的孩子。
在应用程序加载时,我想要处理最初的数千个,而不是每5秒钟滴流一次的后续子项。
您可能会建议我使用值,处理所有内容,然后使用children_added。但我相信如果处理时间过长,我有可能错过一点。
有没有办法在Firebase中做到这一点,保证我不会错过任何一点?
答案 0 :(得分:62)
由于初始预加载数据的child_added
事件将在 value
事件触发之前触发,因此您可以使用value
事件作为一种“初始数据加载”通知。以下是我从another similar StackOverflow question稍微修改过的一些代码。
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会巧妙地缓存此数据,这意味着创建child_added
和value
侦听器只会下载一次数据。为已经越过网线的数据添加新的Firebase监听器是非常便宜的,你应该会经常做这样的事情。
如果您担心在实际不需要时下载所有初始数据,我会在评论中按照@ FrankvanPuffelen的建议使用带时间戳的查询。这非常有效,并使用Firebase查询进行了优化。
答案 1 :(得分:0)
在数据库中添加了一个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);
});
答案 2 :(得分:-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
});
});
答案 3 :(得分:-2)
这个问题有两种可能的解决方案,既不令人满意:
1)为您的孩子设定时间戳,并仅请求时间戳大于&#34;现在&#34;值。这并不是很好,因为您的应用程序之间可能存在同步问题,现在&#34;和#34;现在&#34;将数据推送到Firebase或Firebase服务器值的任何内容#34;现在&#34;。
2)使用值和子项添加。在child_added中看到的任何已经在值中看到的重复项可能会被丢弃。这对于大型数据集来说是不可用的,因为它需要下载所有历史数据TWICE!
为什么不能有&#34; child_added&#34;等命令? DOESN&T?T给了一切吗?