远程iOS客户端成功连接到我,发送订阅命令(它工作得很好),但在"取消订阅"命令我得到下一个错误:
<>之前取消订阅频道:{"channel":"Assessor::StationChannel", "station_id": 1}无法执行来自{"command"=>"unsubscribe", "identifier"=>"{"channel":"Assessor::StationChannel", "station_id": 1}"}的命令[NoMethodError - undefined method ' unsubscribe_from_channel' for nil:NilClass]:/app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/subscriptions。Rb:44:in ' remove_subscription' |/app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/subscriptions。Rb:40:in ' remove' |/app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/subscriptions。Rb:16:in ' execute_command' |/app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/connection/base。Rb:88:in ' dispatch_websocket_message' |/app/vendor/bundle/ruby/2.2.0/gems/actioncable-5.0.0/lib/action_cable/server/worker。b: ' block in invoke'订阅消息格式:
<>之前{"命令":"订阅","标识符":"{"通道":"评估员::StationChannel ","station_id ":1}"}之前取消订阅消息格式:
<>之前{"命令":"退订","标识符":"{"通道":"评估员::StationChannel ","station_id ":1}"}之前我无法在本地主机上重现这个问题,所以也许有人可以帮助我?
我看到了一个类似的错误。我试图通过客户端(JS)取消订阅。我最终发现这是因为javascript的。remove(subscription)取的是订阅,而不是订阅标识符。
这就是我如何得到它的工作没有错误。也许它将帮助您找出从服务器端得到错误的原因。
subscription = App.cable.subscriptions.subscriptions[0]
App.cable.subscriptions.remove(subscription);
(注意,我只是从数组中取出第一个订阅,TODO:搜索我想要删除的订阅)
这是我看到的bug,以及我如何最终找到源代码/答案。我从webclient控制台运行这些:
App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2})
这行行得通,我得到一个"…"正在为rails传输订阅确认s
App.cable.subscriptions.remove({channel: "RoomChannel", room_id: 2})
那句台词大发脾气,对我的孩子大喊大叫,还侮辱我的妻子,看起来像:
[NoMethodError - undefined method `unsubscribe_from_channel' for nil:NilClass]: /usr/local/lib64/ruby/gems/2.3.0/gems/actioncable-5.0.0.1/lib/action_cable/connection/subscriptions.rb:44:in `remove_subscription'
在崩溃之前我还注意到了下面这行。
Unsubscribing from channel:
生成的代码是:logger.info "从频道:#{data['identifier']}取消订阅"。这意味着它没有找到数据['标识符']。我开始调试,看到base的第88行。actioncable中的Rb只获取{"command":"unsubscribe"},而不是{"command":"unsubscribe", "identifier":"(此处为通道名)}
这让我想到了action_cable.js。(我本可以从这里开始,但我讨厌JS。)这是我的问题:函数(订阅)。我发送的是标识符,而不是订阅对象。
Subscriptions.prototype.remove = function(subscription) {
this.forget(subscription);
if (!this.findAll(subscription.identifier).length) {
this.sendCommand(subscription, "unsubscribe");
}
return subscription;
};
App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2})
返回一个订阅对象您必须将其传递给remove
函数
var subscription = App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2});
之后
App.cable.subscriptions.remove(subscription);
经过几次尝试,我终于弄明白了。回复晚了,但这对我有用,希望它对你有用。
App["identifier"].disconnected() #e.g App["chat_4"].disconnect()
=> YourChannel stopped streaming from chat_4 #rails terminal
上面是停止流媒体的那行,下面是订阅频道的方式
App['chat' + id] = App.cable.subscriptions.create({channel:
'YourChannel', chat_id: id}, {
disconnected: function () {
App.cable.subscriptions.remove(this)
},
)}
我知道这是一个老问题,但我也遇到过同样的问题。以上的答案都不适合我,事实上,至少在Rails 5.0.1中,它们是不正确的。这是一个前端问题,但这就是为什么不管你是调用App.yourChannelName.unsubscribe()
还是App.yourChannelName.remove(App.yourChannelName)
。如果你有这样的东西(示例代码是在coffeescript中,所以忽略香草JS中缺乏变量和其他东西):
App.yourChannel = App.cable.subscriptions.create({channel: 'YourChannel', id: id})
...
// do stuff, execute callbacks, whatnot
...
// try to execute unsubscribe
App.yourChannel.unsubscribe()
.unsubscribe()
是订阅原型上的一个方法,它只做return this.consumer.subscriptions.remove(this)
this.consumer.subscriptions
返回订阅的实例,在上面的例子中,它将是App.yourChannel
,并使用subscription的实例调用.remove
方法-即。with App.yourChannel
因此,App.yourChannel.unsubscribe()
与调用App.cable.subscriptions.remove(App.yourChannel)
(或您选择用于存储Subscription实例的任何变量)相同。
我也看到了与OP相同的错误,除了在我的情况下,它是由App.yourChannel.unsubscribe()
被调用两次引起的-第一次是在我通过通道接收到特定数据后立即调用的,第二次是由于在App.yourChannel
重新订阅之前在特定场景中运行自定义清理。
因此,如果您看到类似的错误,我建议您查看服务器日志。你可能会看到像
这样的东西Registered connection (some-id) <-- initial subscription
YourChannel is transmitting the subscription confirmation
...
// other stuff while user is subscribed to the channel
...
Unsubscribing from channel: {"channel":"YourChannel","id":"some-id"} <-- initial unsubscribe call
YourChannel stopped streaming from your_channel_some-id
// some other requests potentially, perhaps some DB queries
...
// there are no requests to subscribe to the channel with the some-id, eg. you won't see this
// Registered connection (some-id)
// YourChannel is transmitting the subscription confirmation
Unsubscribing from channel: {"channel":"YourChannel","id":"some-id"} <-- duplicated unsubscribe call
Could not execute command from {"command"=>"unsubscribe", "identifier"=>"{"channel":"YourChannel","id":"some-id"}"}) [NoMethodError - undefined method `unsubscribe_from_channel' for nil:NilClass]:
基本上,用户订阅,取消订阅,然后再次尝试取消订阅(即使他们不再订阅该频道)