当 iOS 客户端发送"unsubscribe"时,ActionCable 取消订阅回调不起作用



远程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]:

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

相关内容

  • 没有找到相关文章

最新更新