我们正在撰写一款监控在线状态的应用。在多种情况下,我们需要用户打开多个浏览器窗口。我们遇到的问题是,在辅助浏览器窗口中打开并运行firebase js代码后,用户将关闭该辅助窗口。这会将它们的状态设置为在主窗口中脱机,因为onDisconnect事件在辅助窗口中触发。
此方案是否有解决方法?这是否可以使用特殊的/.info/connected位置?
答案 0 :(得分:8)
.info/connected
状态数据仅告知给定客户端他们是否与Firebase服务器相关联,因此在这种情况下它不会帮助您。你可以试试其中一个:
如果变量脱机,请重置该变量
如果您有多个客户端监视同一个变量(多个窗口属于此类别),那么期望它们与存在值冲突是很自然的。让每个人监视变量以进行更改并根据需要进行更正。
var ref = firebaseRef.child(MY_ID).child('status');
ref.onDisconnect().remove();
ref.on('value', function(ss) {
if( ss.val() !== 'online' ) {
// another window went offline, so mark me still online
ss.ref().set('online');
}
});
这很快且易于实现,但可能很烦人,因为我的状态可能会闪烁到离线状态,然后重新联机到其他客户端。当然,这可以通过在触发UI更新之前对任何更改事件进行短暂延迟来解决。
为每个连接指定自己的路径
由于onDisconnect
的目的是告诉您特定客户端是否脱机,因此我们应该自然地为每个客户端提供自己的连接:
var ref = firebaseRef.child(MY_ID).child('status').push(1);
ref.onDisconnect().remove();
使用此用例,每个连接的客户端都会在status
下添加一个新的子项。如果路径不为null,则至少连接了一个客户端。
通过在status
查找真实值来检查在线状态实际上非常简单:
firebaseRef.child(USER_ID).child('status').on('value', function(ss) {
var isOnline = ss.val() !== null;
});
这样做的缺点是你真的只有status
的价值(你不能把它设置为“空闲”和“在线”之类的东西),尽管这也可以解决一点点聪明才智。
在这种情况下,交易不起作用
我的第一个想法是尝试一个事务,所以你可以在打开/关闭每个窗口时增加/减少一个计数器,但transaction
似乎没有onDisconnect
方法。事件。这就是我提出多路径存在价值的方式。
答案 1 :(得分:1)
另一个简单的解决方案(使用angularfire2,但使用纯firebase类似):
const objRef = this.af.database.list('/users/' + user_id);
const elRef = objRef.push(1);
elRef.onDisconnect().remove();
每次打开新选项卡时,都会向阵列中添加一个新元素。 “onDisconnect”的引用与新元素有关,只有它被排除。
当此数组为空时,用户将处于脱机状态。