当iOS客户端发送"取消订阅"

时间:2016-08-18 12:00:17

标签: ios ruby-on-rails ruby websocket actioncable

远程iOS客户端成功连接到我,发送订阅命令(它工作正常),但在"取消订阅"命令我得到下一个错误:

Unsubscribing from channel: {"channel":"Assessor::StationChannel", "station_id": 1}
Could not execute command from {"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.rb:58:in `block in invoke' 

订阅邮件格式:

{"command": "subscribe", "identifier": "{\"channel\":\"Assessor::StationChannel\", \"station_id\": 1}"} 

取消订阅邮件格式:

{"command": "unsubscribe", "identifier": "{\"channel\":\"Assessor::StationChannel\", \"station_id\": 1}"} 

我无法在localhost上重现此问题,所以也许有人可以帮助我?

4 个答案:

答案 0 :(得分:2)

我看到了类似的错误。我试图通过客户端(JS)取消订阅。我最终发现这是因为javascript to .remove(subscription)接受订阅而不是订阅标识符。

这就是我无误地工作的方式。也许它可以帮助您找出从服务器端获取错误的原因。

subscription = App.cable.subscriptions.subscriptions[0]
App.cable.subscriptions.remove(subscription);

(注意,我只是从数组中提取第一个订阅,TODO:搜索我要删除的订阅)

这是我看到的错误以及我最终如何找到源代码/答案。我从webclient控制台运行了这些:

App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2})    

这条线有效,我得到一个" ...正在传输订阅确认"在stdout for 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']}"。这意味着它没有找到数据['标识符']。所以我开始调试,我看到actioncable中base.rb的第88行只获得{"命令":"取消订阅"}而不是{"命令" :"取消订阅","标识符":" (这里有频道名称)}

带我到action_cable.js。 (我本来是从这里开始的,但我讨厌JS。)这是我的问题:功能(订阅)。我发送的是标识符,而不是订阅对象。

Subscriptions.prototype.remove = function(subscription) {
  this.forget(subscription);
  if (!this.findAll(subscription.identifier).length) {
    this.sendCommand(subscription, "unsubscribe");
  }
  return subscription;
};

答案 1 :(得分:1)

ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1 返回一个订阅对象,您必须将其传递到App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2})函数

remove

之后

var subscription = App.cable.subscriptions.create({channel: "RoomChannel", room_id: 2});

答案 2 :(得分:0)

经过几次尝试,我终于明白了。迟到的回复,但这对我有用,希望它能帮到你。

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)
     },
 )}

答案 3 :(得分:0)

我知道这是一个老问题,但是我也遇到了同样的问题。上面的答案都不对我有用,实际上,至少在Rails 5.0.1中,它们是不正确的。好的,这是一个前端问题,但这就是为什么无论您叫App.yourChannelName.unsubscribe()还是App.yourChannelName.remove(App.yourChannelName)

都没关系

例如。如果您有类似的内容(示例代码在coffeescript中,请忽略缺少vars和Vanilla 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方法-即。与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]:

基本上,用户先进行订阅,取消订阅,然后尝试再次取消订阅(即使他们不再订阅该频道了)