7

我们正在编写一个监控在线状态的应用程序。在多种情况下,我们需要用户打开多个浏览器窗口。我们遇到了一个问题,用户在辅助浏览器窗口中打开并运行 firebase js 代码后,将关闭该辅助窗口。这会将它们在主窗口中的状态设置为脱机,因为 onDisconnect 事件会在辅助窗口中触发。

这种情况有解决方法吗?这是可以使用特殊 /.info/connected 位置的地方吗?

4

2 回答 2

9

存在数据仅告诉给定客户端是否已.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事件的方法。这就是我提出多路径存在值的方法。

于 2013-05-09T04:20:19.167 回答
2

另一个简单的解决方案(使用 angularfire2,但使用纯 firebase 类似):

const objRef = this.af.database.list('/users/' + user_id);
const elRef = objRef.push(1);
elRef.onDisconnect().remove();

每次打开新选项卡时,都会向数组中添加一个新元素。“onDisconnect”的引用与新元素有关,并且仅将其排除在外。

当此数组为空时,用户将离线。

于 2017-04-21T14:49:34.007 回答