Rails Action Cable 和 Turbolinks:避免多次绑定

4
我在我的application.html.haml文件中有一段代码,根据一些用户属性决定是否订阅给定的频道。
问题在于,当我点击链接跳转到另一个页面时,由于这段代码在主体中,它会再次订阅用户,而不是保留旧连接,因此我的receive()方法会被执行多次。
以下是我在application.html.haml中的代码:
%html
  %head
    -# other stuff
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
  %body
    -# other stuff

    - if current_user.is_admin?
      :coffee
        MyApp.AdminNotifications.init()

assets/javascripts/notifications/admin_notifications.js.coffee

window.MyApp.AdminNotifications = class AdminNotifications
  @init: ->
    App.cable.subscriptions.create "ProductsChannel",
      received: (data) ->
        console.log 'Data Received' # This is being executed multiple times

第一次加载页面时,当我向该频道广播消息时,控制台只会记录“Data Received”一次。 我单击链接以重定向到另一页,我向该频道广播新消息,现在控制台将记录“Data Received”两次。以此类推...
实际上,当我在Chrome控制台上运行时:
App.cable.subscriptions.subscriptions

它会为同一频道返回多个订阅(每次我点击链接并重定向到不同页面时都会返回一次)。

注意:我没有在此帖子中添加更多的Action Cable设置,因为它已经正常工作。

我该如何避免这种情况?有什么想法吗?

2个回答

0
写在标签里面怎么样? 也许事件已经被Turbolinks多次注册了。
%html
  %head
    -# other stuff
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'

    - if current_user.is_admin?
      :coffee
        MyApp.AdminNotifications.init()

  %body
    -# other stuff

0

看起来你只需要一个 MyApp.AdminNotifications 的实例,所以你可能只需要添加一个类属性来标记该类已被初始化:

window.MyApp.AdminNotifications = class AdminNotifications
  @init: ->
    unless @initialized
      App.cable.subscriptions.create "ProductsChannel",
        received: (data) ->
          console.log 'Data Received'
      @initialized = true

在未来,您可能希望封装Action Cable API以管理自己的订阅。
通常在使用Turbolinks时,最好将尽可能多的内容包含在应用程序.js文件中,而不是内联脚本(请参见:https://github.com/rails/rails/pull/23012#issue-125970208)。我猜你使用了内联脚本,这样你就可以有条件地运行它(if current_user.is_admin?)。一种流行的方法是使用元标记传递此数据,在您的头部中:
<meta name="current-user-is-admin" content="true">

那么你可以有:

window.MyApp.User = class User
  constructor: ->
    @isAdmin = @getMeta('current-user-is-admin') == 'true'

  getMeta: (name) ->
    meta = document.querySelector("meta[name=#{name}]")
    meta.getAttribute('content') if meta

最后,要从布局中删除AdminNotifications的初始化代码,请在你的 application.js 文件中任意位置添加以下代码:
document.addEventListener('turbolinks:load', ->
  window.MyApp.currentUser = new window.MyApp.User
  window.MyApp.AdminNotifications.init() if window.MyApp.currentUser.isAdmin
)

希望这能有所帮助!

谢谢您的奖赏!如果您发现这个答案解决了您的问题,请将其标记为“接受”。再次感谢 :) - Dom Christie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接