【问题标题】:Detecting Last Window/Tab Close with ActionCable使用 ActionCable 检测最后一个窗口/选项卡关闭
【发布时间】:2017-06-01 12:28:17
【问题描述】:

我正在尝试找到一种方法来检测用户的最后一个窗口或选项卡是否正在关闭,以便我可以进行一些清理;但我似乎无法找到一种方法来检测它实际上是用户的最后一个连接。我有一个模型可以跟踪与我的频道的连接,并且我不想在用户断开连接时删除用户的连接记录,如果他们有其他活动选项卡打开连接。

所以我需要以某种方式检查每个断开连接,看看它们是否是具有相同标识符的其他活动连接。

我尝试在断开连接方法中设置对 RemoteConnections 的检查。但是当它被调用时,似乎正在关闭的连接仍然在 RemoteConnections 下返回。

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.username
      logger.debug self.current_user.username + " now connected."
    end

    def disconnect
      self.close()
      logger.debug ActionCable.server.remote_connections.where(current_user: current_user)
      logger.debug ActionCable.server.remote_connections.where(current_user: current_user).identifiers
      logger.debug ActionCable.server.remote_connections.where(current_user: current_user).identifiers.inspect()
    end
end

即使使用该标识符的最后一个连接正在关闭,此设置也会返回以下内容:

[ActionCable] [swachtma@gmail.com] UserChannel stopped streaming from user:Z2lkOi8vYWxseWNoYXQvVXNlci80Nw
[ActionCable] [swachtma@gmail.com] #<ActionCable::RemoteConnections::RemoteConnection:0x00000007062690>
[ActionCable] [swachtma@gmail.com] #<Set:0x00000007791b78>
[ActionCable] [swachtma@gmail.com] #<Set: {:current_user}>

到目前为止,我一直在通过建立一个模型来解决这个问题,该模型只是为了跟踪每个频道打开和关闭的连接。但这会增加很多开销,而且管理起来很麻烦。

任何人都可以建议一种方法来管理这个吗?我一直在搜索 ActionCable 的 API 文档,结果一无所获。

【问题讨论】:

    标签: ruby-on-rails actioncable


    【解决方案1】:

    我找到了一个可能不适用于每个人的解决方案,但由于这些是几个 SO 问题,没有答案,我想我会发布我最终的结果,也许它会帮助其他人。

    我放弃了查询有线服务器以计算活动连接数的想法。如果目前可行,我显然还不够聪明,无法找到答案。

    我还尝试使用 Active Record 来计算活动连接,存储 GIDS 以识别它们,并在最后一个连接关闭时进行清理。它奏效了……但我不是粉丝,因为它添加了大量额外的查询、跟踪订阅的新模型以及对清理工作时间的高度敏感。可能,但丑陋。

    相反,我采用了“主”和“从”的概念、连接以及额外的 UserChannel(由我的用户身份验证驱动)。基本上,启动第一个订阅的连接成为“主”连接(在我的例子中是聊天室)。当主人加入时,我通过 UserChannel 向所有其他活动的窗口/选项卡广播一个通知,这些窗口/选项卡被认证为同一用户。那些接收到这个广播的人,通过在一个单独但成对的从属通道上建立连接来跟随主连接。 “主”连接也建立了自己的匹配“从”连接。

    所以我为每个聊天室维护 2 个频道:room_#slave 和 room#_master

    聊天室活动的所有广播都发生在“从属”频道上(因为它可用于用户的所有会话,而只有一个窗口/选项卡订阅了主频道)。新消息、用户出口、入口等都在这里广播。

    “主”通道仅用于处理设置和拆卸。当用户加入时,主频道的“订阅”方法通过“从”频道将该用户的条目广播给其他用户。

    当主连接关闭时,它的“未订阅”方法广播退出,处理活动记录清理,并向所有从连接广播一条消息,让该用户进入挂起状态。然后从属设备可以选择加入(通过用户操作)成为新的主连接,在这种情况下连接被恢复。

    这是我能找到的最佳平衡;就 ActiveRecord 而言,连接只计算一个窗口/选项卡。如果该窗口关闭,则用户已“离开”。但是,从属频道让我可以在所有用户的浏览器窗口/标签中保持一个共同的状态,因为他们仍然见证所有发送的广播。如果用户不小心关闭了“主”连接,他们可以轻松地重新加入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-09
      • 2021-07-29
      • 1970-01-01
      • 2022-11-09
      • 1970-01-01
      • 2020-04-13
      相关资源
      最近更新 更多