我正在使用private_pub作为宝石来实现与Facebook提供的通知系统非常相似的通知系统。为此,我订阅视图中的频道并从各个地方(不同的控制器)发布。
正在发生的事情是,有时我会为一次订阅获得大量发布。你知道为什么会这样吗?
我的第一个怀疑是我可能会多次调用我的通知方法(在某种循环或某种情况下,但我可以看到它只被调用一次,所以我猜问题必须介于两者之间发布/子图层,很可能是因为我在通知视图时出错了。
接下来,我将介绍我实施的一些片段。
在我网站的_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。
答案 0 :(得分: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
语句来调用if
方法时嵌入在html中的JavaScript代码,该语句检查订阅对象中是否已存在该通道。如果它不存在,它允许您订阅它,否则它不会。
raw(
"if(typeof PrivatePub.subscriptions['#{channel}'] === 'undefined') {
PrivatePub.sign(#{subscription.to_json})
}")
希望这有帮助!
答案 1 :(得分:0)
我认为我们遇到了同样的问题:有时我会收到同一条消息的多个通知...例如在聊天中我收到多条相同的消息,但如果我重新加载页面和聊天,则消息只有一条!
在我的情况下,问题是我使用AJAX加载页面(以及加载聊天)所以基本上我总是有相同的页面并加载两次聊天,即加载聊天,关闭聊天和加载再次,它导致对同一个频道有两个订阅,因此有两个相同的消息!
目前没有任何'取消订阅'的方法,所以两个避免这种方法的唯一方法就是确保每页加载只进行一次订阅......
希望有用
答案 2 :(得分: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
很邋但但它有效。我更愿意知道为什么我会在同一个频道上获得这些多个订阅以及如何阻止它们,这比这个解决方法要好得多。