【问题标题】:Action Cable: How to get the client's subscription name when the client unsubscribes?Action Cable:客户端退订时如何获取客户端的订阅名?
【发布时间】:2017-04-21 09:08:03
【问题描述】:

我正在使用 Devise 和 gem 'devise_token_auth' 在 Rails 5 API Action Cable 中实现聊天。

我有一个带有参数化订阅的ChatRequestChannel

stream_from "chat_request_#{chat_request_chanel_token}_channel"

我需要以某种方式可靠地检索 unsubscribed 挂钩内的 chat_request_chanel_token 值 - 以向其他订阅者发送消息。这是我的代码:

class ChatRequestChannel < ApplicationCable::Channel
  def subscribed 

    answerer = params["answerer"]

    chat_request_chanel_token = answerer

    answerer_user = User.find_by email: answerer

    if answerer_user

      stream_from "chat_request_#{chat_request_chanel_token}_channel"

    else
# http://api.rubyonrails.org/classes/ActionCable/Channel/Base.html#class-ActionCable::Channel::Base-label-Rejecting+subscription+requests
      reject

    end

  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed

      chat_request_chanel_token = "What to put here????"

      message = "Client disconnected"  

      ActionCable.server.broadcast "chat_request_#{chat_request_chanel_token}_channel",
                                   disconnected: message

  end
end

所有客户端订阅ChatRequestChannel 并使用这样的命令(answerer 参数因客户端而异):

{"command":"subscribe","identifier":"{\"channel\":\"ChatRequestChannel\",\"answerer\":\"client1@example.com\"}"}

unsubscribed 钩子实际上是在客户端与 Action Cable 断开连接时调用的。所以我无法向unsubscribed 提供任何参数。

我建议每个客户应该只一个(每个参数)参数化订阅ChatRequestChannel。它是否存储在 Action Cable 中的某个位置并且可以检索?

【问题讨论】:

    标签: ruby-on-rails actioncable


    【解决方案1】:

    我可能找到了。里面有一个数组streams

    /var/lib/gems/2.3.0/gems/actioncable-5.0.1/lib/action_cable/channel/streams.rb

    def stream_from(broadcasting, callback = nil, coder: nil, &block)
            broadcasting = String(broadcasting)
    
            # Don't send the confirmation until pubsub#subscribe is successful
            defer_subscription_confirmation!
    
            # Build a stream handler by wrapping the user-provided callback with
            # a decoder or defaulting to a JSON-decoding retransmitter.
            handler = worker_pool_stream_handler(broadcasting, callback || block, coder: coder)
            streams << [ broadcasting, handler ]
    
            connection.server.event_loop.post do
              pubsub.subscribe(broadcasting, handler, lambda do
                ensure_confirmation_sent
                logger.info "#{self.class.name} is streaming from #{broadcasting}"
              end)
            end
          end
    

    streams &lt;&lt; [ broadcasting, handler ]这一行。

    这是我基于它的代码:

    module ApplicationCable
      class Channel < ActionCable::Channel::Base
        include ApplicationHelper
    
          def stream_name
            streams.try(:[],0).try(:[],0)
          end
    
          def token_from_stream_name
    
            stream_name ? stream_name.gsub(channel_name,"").slice(1..-"_channel".size-1) : ""
    
          end
      end
    end
    

    stream_name 方法现在可以在 unsubscribe 挂钩中使用。当客户端与服务器套接字断开连接时,会自动为每个客户端的订阅(对该频道的订阅)调用unsubscribed 挂钩。在unsubscribe 中调用stream_name 会返回当前正在停止的订阅的名称,以便您通知该频道的所有其他订阅者:

    class ChatChannel < ApplicationCable::Channel
     .... 
      def unsubscribed
        # Any cleanup needed when channel is unsubscribed
    
        message = { user_id: current_user.id, online: :off }
    
        ActionCable.server.broadcast stream_name, chat_cancel: message      
      end
    ....
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-28
      • 1970-01-01
      • 2017-12-25
      • 2017-12-01
      • 2023-04-03
      • 2022-12-12
      • 2023-01-31
      • 2018-12-30
      相关资源
      最近更新 更多