【问题标题】:RubyOnRails - PrivatePub Gem - Multiple Publishes to view with single SubscriptionRuby On Rails - Private Pub Gem - 通过单个订阅查看多个发布者
【发布时间】:2016-02-19 23:35:15
【问题描述】:

我使用 private_pub 作为实现通知系统的 gem,就像 Facebook 提供的那样。为此,我订阅了视图中的频道并从不同的地方(不同的控制器)发布。

发生的情况是,有时我会为单个订阅获得大量发布。您知道为什么会发生这种情况吗?

我的第一个怀疑是我可能多次调用我的 notify 方法(在某种循环或其他情况下,但我可以看到它只被调用一次,所以我猜问题一定是介于两者之间pub/sub 层,很可能是因为我在通知 View 时做错了什么。

接下来我介绍一些我的实现的sn-ps。

在我网站的 _header.html.erb 部分,我订阅了用户的通知频道,如下所示:

例如,在我的friendships_controller 中,添加朋友时,我会生成一些html 来显示通知并发布带有前置通知的jquery,如下所示:

html_text = render_to_string(:partial => 'notifications/notification', :locals => { notification: notification }, :formats => [:html]).squish jquery = "$('#notifications_" + user.id.to_s + "').prepend('#{html_text}');" PrivatePub.publish_to("/notifications/" + user.id.to_s, jquery)

抱歉,帖子太长了,希望你们中的一些人能帮助我。提前致谢。

顺便说一句,我正在运行带有 Ruby 2.0.0p247 的 Rails 4.0.0。

【问题讨论】:

    标签: ruby-on-rails ruby channel private-pub


    【解决方案1】:

    我知道这是一个老问题,但有些人可能仍在为这个问题苦苦挣扎。

    在我的例子中,我多次订阅同一个频道,因为 subcribe_to 方法位于通过 AJAX 加载的选项卡内。因此,每次我在不重新加载页面的情况下选择该选项卡时,它都会再次为我订阅同一个频道,从而导致多次 publish_to 执行次数等于我选择该选项卡的次数。

    虽然这可能与您所面临的情况不完全相同,但此解决方案可能非常适合您的需求。

    我为解决这个问题所做的就是用这个覆盖类 private_pub/lib/private_pub/view_helpers.rb 和方法 subscribe_to

    module PrivatePub
      module ViewHelpers
    
        # Subscribe the client to the given channel. This generates
        # some JavaScript calling PrivatePub.sign with the subscription
        # options.
        def subscribe_to(channel)
          subscription = PrivatePub.subscription(:channel => channel)
          content_tag "script", :type => "text/javascript" do
            raw(
              "if(typeof PrivatePub.subscriptions['#{channel}'] === 'undefined') {
                PrivatePub.sign(#{subscription.to_json});
              }")
          end
        end
      end
    end
    

    我更改的是嵌入在 html 中的 JavaScript 代码,当调用 subscribe_to 方法时,添加了一个检查频道是否已存在于订阅对象中的 if 语句。如果它不存在,它让你订阅它,否则它不会。

    raw(
        "if(typeof PrivatePub.subscriptions['#{channel}'] === 'undefined') {
           PrivatePub.sign(#{subscription.to_json})
         }")
    

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      我认为我们有同样的问题:有时我会收到同一条消息的多个通知...例如,在聊天中我收到多条相同的消息,但如果我重新加载页面和聊天,则消息只有一条!

      在我的情况下,问题是我使用 AJAX 加载页面(以及加载聊天)所以基本上我总是有相同的页面并加载两次聊天,即加载聊天,关闭聊天并加载再次,它导致对同一频道有两个订阅,因此有两条相同的消息!

      目前没有任何“取消订阅”方法,所以避免这种情况的唯一方法是确保每次页面加载只订阅一次...

      希望有用

      【讨论】:

        【解决方案3】:

        我也遇到过这个问题,我想...我怀疑我正在以某种方式进行多次订阅,并且我怀疑这与 Turbolinks 有关。当您在没有完全重新加载的情况下访问其他页面时,额外的订阅似乎会堆积起来。也许某种缓存?

        我想出了一个低俗的解决方法来完成这项工作。不过,这不是一个很好的解决方案,我宁愿知道为什么会发生多次订阅。不过,这种模式可以解决问题。

        基本上,只需在添加之前删除您将要插入到 DOM 中的任何内容。通常这将是一个您已用 dom_id 标记的对象,但如果您要插入多个东西,添加一些可以让您全部获取它们的类可能会更方便。

        假设您正在创建一些 @object,它有一个要插入到 dom 中的部分,并将其附加到 #some_destination。在您的create.js.slim 中(如果必须,请在精神上转换为 erb/haml/etc)

        - publish_to some_channel do
          | $('##{dom_id @object').remove();
          | $('#some_destination').append('#{j render(@object)');
        

        然后在部分_object.html.slim 中确保它被正确标记

        div id=dom_id(object)
          = object.to_text
        

        低俗但有效。我想知道为什么我要让这些多个订阅到同一个频道以及如何阻止它们,这比这种解决方法要好得多。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-26
          • 1970-01-01
          • 2017-11-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多