Action Cable:客户端取消订阅时如何获取客户端的订阅名称?
我正在使用Devise和gem'devise_token_auth'在Rails 5 API Action Cable中实现聊天功能。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
PARAM从客户端变化到客户端):
{"command":"subscribe","identifier":"{\"channel\":\"ChatRequestChannel\",\"answerer\":\"[email protected]\"}"}
的unsubscribed
钩实际上被调用时,客户端断开连接来自Action Cable。所以我不能提供任何参数unsubscribed
。
我建议每个客户端应该只有一个(每个参数)参数化订阅ChatRequestChannel
。它是否存储在Action Cable内的某个地方,可以被检索?
我大概找到了。里面有一个Array 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 << [ 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