【问题标题】:Rails Action Cable and Turbolinks: avoid multiple bindingsRails Action Cable 和 Turbolinks:避免多重绑定
【发布时间】:2017-05-07 22:05:32
【问题描述】:

我的 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

第一次加载页面时,当我向该频道广播消息时,控制台只记录一次“收到的数据”。 我单击要重定向到另一个页面的链接,我向该频道广播了一条新消息,现在控制台正在记录“接收到的数据”两次。到目前为止……

其实,当我在 chrome 的控制台上运行时:

App.cable.subscriptions.subscriptions

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

注意:我没有在这篇文章中添加更多动作电缆设置,因为它工作正常。

我怎样才能避免这种情况?有什么想法吗?

【问题讨论】:

    标签: javascript ruby-on-rails turbolinks actioncable turbolinks-5


    【解决方案1】:

    看起来您只需要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 时的一般规则,最好在 application.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
    )
    

    希望有帮助!

    【讨论】:

    • 感谢您的赏金!如果您发现此答案可以解决您的问题,请将其标记为“已接受”。再次感谢:)
    【解决方案2】:

    用头脑而不是身体写作怎么样? 也许该事件已被 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
    

    【讨论】:

      猜你喜欢
      • 2018-03-28
      • 2015-08-21
      • 1970-01-01
      • 2019-02-15
      • 1970-01-01
      • 1970-01-01
      • 2016-09-27
      • 1970-01-01
      • 2017-07-10
      相关资源
      最近更新 更多