Rails 客户端订阅 ActionCable 的 Channel,JSON 解析错误

jojoma · 2016年12月25日 · 最后由 gyorou 回复于 2016年12月26日 · 2223 次阅读

我用 ActionCable(5.0.0 版本)用作 websocket 服务端,全是 setup 基本操作。 自定义的东西也就是在哪里 broadcast

after_create_commit :message_broadcast
def call_screen_broadcast
  ActionCable.server.broadcast 'message_channel', message: content
end

然后在浏览器,尝试去连接 ws

ws = new WebSocket("ws://localhost:3000/cable")

开发日志返回

Started GET "/cable" for ::1 at 2016-12-25 13:04:05 +0800
Started GET "/cable/" [WebSocket] for ::1 at 2016-12-25 13:04:05 +0800
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)

能在浏览器的 network 看到 ping 在跳,理论上已经连接上了 ws。

但是想要订阅 channel 的时候,问题就来了

搜过这个问题,所以知道需要使用 {"command":"subscribe","identifier":"{\"channel\":\"MessageChannel\"}"}这样的 json

但是我在浏览器 ws.send({"command":"subscribe","identifier":"{\"channel\":\"MessageChannel\"}"}) 日志里面却返回错误

There was an exception - JSON::ParserError(419: unexpected token at 'object Object]')
/Users/jojoma/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/json/common.rb:156:in `parse'
/Users/jojoma/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/json/common.rb:156:in `parse'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/json/decoding.rb:21:in `decode'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/connection/base.rb:164:in `decode'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/connection/base.rb:90:in `dispatch_websocket_message'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/server/worker.rb:58:in `block in invoke'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/server/worker.rb:39:in `block in work'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:126:in `call'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:455:in `call'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:448:in `block (2 levels) in around'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:286:in `block (2 levels) in halting'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/server/worker/active_record_connection_management.rb:14:in `block in with_database_connections'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/connection/tagged_logger_proxy.rb:22:in `block in tag'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/tagged_logging.rb:70:in `block in tagged'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/tagged_logging.rb:26:in `tagged'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/tagged_logging.rb:70:in `tagged'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/connection/tagged_logger_proxy.rb:22:in `tag'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/server/worker/active_record_connection_management.rb:14:in `with_database_connections'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:382:in `block in make_lambda'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:285:in `block in halting'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:447:in `block in around'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:455:in `call'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:448:in `block (2 levels) in around'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:286:in `block (2 levels) in halting'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/engine.rb:60:in `block (4 levels) in <class:Engine>'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/execution_wrapper.rb:76:in `wrap'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/engine.rb:55:in `block (3 levels) in <class:Engine>'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:391:in `instance_exec'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:391:in `block in make_lambda'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:285:in `block in halting'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:447:in `block in around'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:455:in `call'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:101:in `__run_callbacks__'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:750:in `_run_work_callbacks'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/activesupport-5.0.0/lib/active_support/callbacks.rb:90:in `run_callbacks'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/server/worker.rb:38:in `work'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/server/worker.rb:56:in `invoke'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/actioncable-5.0.0/lib/action_cable/server/worker.rb:51:in `block in async_invoke'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/concurrent-ruby-1.0.2/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/concurrent-ruby-1.0.2/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/concurrent-ruby-1.0.2/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/concurrent-ruby-1.0.2/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/concurrent-ruby-1.0.2/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch'
/Users/jojoma/.rvm/gems/ruby-2.3.1/gems/concurrent-ruby-1.0.2/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'

我在action_cable/connection/base.rb:90:in dispatch_websocket_message这里打印了一下

发现,待处理的 websocket_message 居然变成了 "[object Object]" 而页面上,rails 自己的 js 产生的客户端订阅 channel,传过去的 websocket_message 是没有问题的,打印出来是{"command":"subscribe","identifier":"{\"channel\":\"MessageChannel\"}"}

不知道有人遇到过这样的问题吗?怎么跟最初 github issue 里面描述的不一样呢?

ws.send("{\"command\":\"subscribe\",\"identifier\":\"{\\\"channel\\\":\\\"CallScreenChannel\\\"}\"}")

这样就好了....

需要 登录 后方可回复, 如果你还没有账号请 注册新账号