如何使用 Firebase 将初始数据加载与增量 children 分开?
How to separate initial data load from incremental children with Firebase?
我有一个应用程序,每 5 秒左右就会向 Firebase 添加新的 children。我有几千个children.
在应用程序加载时,我希望以不同于后续 children 每 5 秒滴流的方式处理最初的数千个。
您可能会建议我使用值,处理所有内容,然后使用 children_added。但我相信,如果处理时间过长,我可能会漏掉一点。
有没有一种方法可以在 Firebase 中做到这一点,保证我不会错过任何一点?
这个问题有两种可能的解决方案,都不令人满意:
1) 为您的 children 加上时间戳,并且只请求时间戳大于 "now" 值的 children。这不是很好,因为您的应用程序 "now" 和 "now" 之间可能存在同步问题,无论是将数据推送到 Firebase 还是 "now".[=10= 的 Firebase 服务器值]
2) 使用值并添加 child。在 child_added 中看到的任何已在值中看到的重复项可能会被丢弃。这对于大型数据集是不可用的,因为它需要下载所有历史数据两次!
为什么不能有像 "child_added" 这样的命令,它永远不会提供所有信息?
由于 child_added
初始预加载数据的事件将在 之前触发 value
事件,您可以使用 value
事件作为一种 "initial data loaded" 通知。这是我从 another similar Whosebug 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 查询进行了优化。
改进了@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
});
});
在数据库中添加了一个 createdAt 时间戳,并用当前时间限制了 child_added,这对我来说似乎工作正常。
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);
});
我有一个应用程序,每 5 秒左右就会向 Firebase 添加新的 children。我有几千个children.
在应用程序加载时,我希望以不同于后续 children 每 5 秒滴流的方式处理最初的数千个。
您可能会建议我使用值,处理所有内容,然后使用 children_added。但我相信,如果处理时间过长,我可能会漏掉一点。
有没有一种方法可以在 Firebase 中做到这一点,保证我不会错过任何一点?
这个问题有两种可能的解决方案,都不令人满意:
1) 为您的 children 加上时间戳,并且只请求时间戳大于 "now" 值的 children。这不是很好,因为您的应用程序 "now" 和 "now" 之间可能存在同步问题,无论是将数据推送到 Firebase 还是 "now".[=10= 的 Firebase 服务器值]
2) 使用值并添加 child。在 child_added 中看到的任何已在值中看到的重复项可能会被丢弃。这对于大型数据集是不可用的,因为它需要下载所有历史数据两次!
为什么不能有像 "child_added" 这样的命令,它永远不会提供所有信息?
由于 child_added
初始预加载数据的事件将在 之前触发 value
事件,您可以使用 value
事件作为一种 "initial data loaded" 通知。这是我从 another similar Whosebug 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 查询进行了优化。
改进了@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
});
});
在数据库中添加了一个 createdAt 时间戳,并用当前时间限制了 child_added,这对我来说似乎工作正常。
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);
});