1

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

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

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

接下来,我将介绍一些我的实现片段。

在我网站的 _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。

4

3 回答 3

2

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

就我而言,我多次订阅同一个频道,因为该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

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

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

希望这可以帮助!

于 2016-02-19T15:35:15.407 回答
0

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

就我而言,问题是我使用 AJAX 加载页面(也加载聊天)所以基本上我总是有相同的页面并加载两次聊天,即加载聊天,关闭聊天并再次加载,它导致有两个订阅相同的频道,因此两个相同的消息!

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

希望有用

于 2013-09-10T10:40:29.993 回答
0

我也遇到了这个问题,我想......我怀疑我正在以某种方式多次订阅,并且我怀疑它与 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

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

于 2013-12-03T12:29:45.497 回答