您将如何使用 ActionCable 订阅特定流
How would you subscribe to specific stream using ActionCable
我有一个本机 rails 网络应用程序和一个具有聊天组件的 iOS 应用程序。我正在使用 ActionCable 提供实时消息传递。
当在 MessageController 中创建消息时,服务器向 MessageChannel 中的两个流广播
- 呈现 html 进入网络聊天
- json 对象转到 iOS 应用程序
你能创建流特定订阅吗?也就是在客户端,能不能从json广播中过滤掉html广播?
或者我应该创建一个 ApiMessageChannel 和一个 web MessageChannel 吗?这感觉像是不必要的重复,因为创建将始终广播到网络和 api.
MessageChannel
class MessageChannel < ApplicationCable::Channel
def subscribed
stop_all_streams
stream_for Group.find(params["id"])
stream_from "message:messages_api_#{params["id"]}"
end
end
MessageController
def create
# ...
MessageChannel.broadcast_to group, message: render_to_string(message, locals: { previous_message: previous_message, type: group.type, current_user: current_user })
MessageChannel.broadcast_to "messages_api_#{group.id}", message: ApplicationController.render_with_signed_in_user(current_user, json: { sender: current_user.username, content: message.body })
end
聊天室控制器
import { Controller } from "stimulus"
import consumer from "channels/consumer"
export default class extends Controller {
static targets = [ "messages", "newMessage" ]
connect() {
this.subscription = consumer.subscriptions.create({ channel: "MessageChannel", id: this.data.get("id") }, {
connected: this._connected.bind(this),
disconnected: this._disconnected.bind(this),
received: this._received.bind(this)
})
}
disconnect() {
consumer.subscriptions.remove(this.subscription)
}
_connected() {
}
_disconnected() {
}
_received(data) {
if (data.message) {
this.messagesTarget.insertAdjacentHTML('beforeend', data.message);
$('.js-chat-messages').scrollTop($('.js-chat-messages')[0].scrollHeight);
}
}
clearMessage(event) {
this.newMessageTarget.value = ''
}
}
Swift iOS
static var ChannelIdentifier = "MessageChannel"
let actionCableClient = ActionCableClient(url: URL(string: "wss://localhost:3000/cable")!)
actionCableClient.headers = [
"Authorization": token,
"Accept": "application/json"
]
actionCableClient.connect()
let room_identifier = ["id" : "12"]
actionCableChannel = actionCableClient.create(ActionCableController.ChannelIdentifier, parameters: room_identifier, autoSubscribe: true, bufferActions: true )
actionCableChannel?.onReceive = { (data: Any?, error: Error?) in
print("recieved message!")
if let error = error {
print("ERROR: Unable to receive message from ActionCable Channel: \(error.localizedDescription)")
return
}
```
根据文档,您可以知道如下:
found out that the subscribed method is called via client-side javascript, not by the rails controller.
根据你的问题,你应该订阅特殊资源吧?
要订阅特定的命名流,您可以:
class MessageChannel < ApplicationCable::Channel
def subscribed
# stream_from "message:messages_web"
# stream_from "message:messages_api"
# stream_from "message:messages_test"
stream_from "message:messages_#{params[:type]}"
# !! can also add in other parameters and add those on the client side for stream specific filtering
# stream_from "message:messages_#{params[:type]}_#{params[:id]}"
end
end
class MessagesController < ApplicationController
def create
MessageChannel.broadcast_to "messages_web", 'web'
MessageChannel.broadcast_to "messages_api", 'api'
MessageChannel.broadcast_to "messages_test", 'test'
end
end
import consumer from "channels/consumer"
this.subscription = consumer.subscriptions.create({ channel: "MessageChannel", type: 'web'}, {
connected: this._connected.bind(this),
disconnected: this._disconnected.bind(this),
received: this._received.bind(this)
})
这只会收到来自“消息:messages_web”的消息
我有一个本机 rails 网络应用程序和一个具有聊天组件的 iOS 应用程序。我正在使用 ActionCable 提供实时消息传递。
当在 MessageController 中创建消息时,服务器向 MessageChannel 中的两个流广播
- 呈现 html 进入网络聊天
- json 对象转到 iOS 应用程序
你能创建流特定订阅吗?也就是在客户端,能不能从json广播中过滤掉html广播?
或者我应该创建一个 ApiMessageChannel 和一个 web MessageChannel 吗?这感觉像是不必要的重复,因为创建将始终广播到网络和 api.
MessageChannel
class MessageChannel < ApplicationCable::Channel
def subscribed
stop_all_streams
stream_for Group.find(params["id"])
stream_from "message:messages_api_#{params["id"]}"
end
end
MessageController
def create
# ...
MessageChannel.broadcast_to group, message: render_to_string(message, locals: { previous_message: previous_message, type: group.type, current_user: current_user })
MessageChannel.broadcast_to "messages_api_#{group.id}", message: ApplicationController.render_with_signed_in_user(current_user, json: { sender: current_user.username, content: message.body })
end
聊天室控制器
import { Controller } from "stimulus"
import consumer from "channels/consumer"
export default class extends Controller {
static targets = [ "messages", "newMessage" ]
connect() {
this.subscription = consumer.subscriptions.create({ channel: "MessageChannel", id: this.data.get("id") }, {
connected: this._connected.bind(this),
disconnected: this._disconnected.bind(this),
received: this._received.bind(this)
})
}
disconnect() {
consumer.subscriptions.remove(this.subscription)
}
_connected() {
}
_disconnected() {
}
_received(data) {
if (data.message) {
this.messagesTarget.insertAdjacentHTML('beforeend', data.message);
$('.js-chat-messages').scrollTop($('.js-chat-messages')[0].scrollHeight);
}
}
clearMessage(event) {
this.newMessageTarget.value = ''
}
}
Swift iOS
static var ChannelIdentifier = "MessageChannel"
let actionCableClient = ActionCableClient(url: URL(string: "wss://localhost:3000/cable")!)
actionCableClient.headers = [
"Authorization": token,
"Accept": "application/json"
]
actionCableClient.connect()
let room_identifier = ["id" : "12"]
actionCableChannel = actionCableClient.create(ActionCableController.ChannelIdentifier, parameters: room_identifier, autoSubscribe: true, bufferActions: true )
actionCableChannel?.onReceive = { (data: Any?, error: Error?) in
print("recieved message!")
if let error = error {
print("ERROR: Unable to receive message from ActionCable Channel: \(error.localizedDescription)")
return
}
```
根据文档,您可以知道如下:
found out that the subscribed method is called via client-side javascript, not by the rails controller.
根据你的问题,你应该订阅特殊资源吧?
要订阅特定的命名流,您可以:
class MessageChannel < ApplicationCable::Channel
def subscribed
# stream_from "message:messages_web"
# stream_from "message:messages_api"
# stream_from "message:messages_test"
stream_from "message:messages_#{params[:type]}"
# !! can also add in other parameters and add those on the client side for stream specific filtering
# stream_from "message:messages_#{params[:type]}_#{params[:id]}"
end
end
class MessagesController < ApplicationController
def create
MessageChannel.broadcast_to "messages_web", 'web'
MessageChannel.broadcast_to "messages_api", 'api'
MessageChannel.broadcast_to "messages_test", 'test'
end
end
import consumer from "channels/consumer"
this.subscription = consumer.subscriptions.create({ channel: "MessageChannel", type: 'web'}, {
connected: this._connected.bind(this),
disconnected: this._disconnected.bind(this),
received: this._received.bind(this)
})
这只会收到来自“消息:messages_web”的消息