我们正在编写一个监控在线状态的应用程序。在多种情况下,我们需要用户打开多个浏览器窗口。我们遇到了一个问题,用户在辅助浏览器窗口中打开并运行 firebase js 代码后,将关闭该辅助窗口。这会将它们在主窗口中的状态设置为脱机,因为 onDisconnect 事件会在辅助窗口中触发。
这种情况有解决方法吗?这是可以使用特殊 /.info/connected 位置的地方吗?
我们正在编写一个监控在线状态的应用程序。在多种情况下,我们需要用户打开多个浏览器窗口。我们遇到了一个问题,用户在辅助浏览器窗口中打开并运行 firebase js 代码后,将关闭该辅助窗口。这会将它们在主窗口中的状态设置为脱机,因为 onDisconnect 事件会在辅助窗口中触发。
这种情况有解决方法吗?这是可以使用特殊 /.info/connected 位置的地方吗?
存在数据仅告诉给定客户端是否已.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
. 如果路径不为空,则至少连接了一个客户端。
实际上,通过在以下位置查找真实值来检查在线状态相当简单status
:
firebaseRef.child(USER_ID).child('status').on('value', function(ss) {
var isOnline = ss.val() !== null;
});
这样做的一个缺点是你真的只有一个真正的价值status
(你不能将它设置为“空闲”与“在线”之类的东西),尽管这也可以通过一点点独创性来解决。
在这种情况下交易不起作用
我的第一个想法是尝试事务,因此您可以在每个窗口打开/关闭时增加/减少计数器,但似乎没有transaction
关闭onDisconnect
事件的方法。这就是我提出多路径存在值的方法。
另一个简单的解决方案(使用 angularfire2,但使用纯 firebase 类似):
const objRef = this.af.database.list('/users/' + user_id);
const elRef = objRef.push(1);
elRef.onDisconnect().remove();
每次打开新选项卡时,都会向数组中添加一个新元素。“onDisconnect”的引用与新元素有关,并且仅将其排除在外。
当此数组为空时,用户将离线。