【发布时间】:2017-01-09 09:07:49
【问题描述】:
假设我有一个可能如下所示的状态列表:
ul#list
- @list_items.each do |item|
li.loading Item #{item.id} - Status: #{item.status}
li Item #{item.id} - Status: #{item.status}
li Item #{item.id} - Status: #{item.status}
li.loading Item #{item.id} - Status: #{item.status}
这使我:
Item 1 - Status: Loading
Item 2 - Status: Finished
Item 3 - Status: Finished
Item 4 - Status: Loading
我想做的是定期轮询个人列表项的更改,如果状态发生更改,则刷新它们。到目前为止,我能够轻松刷新整个列表:
ul#list
== render 'status_list', list_items: @list_items
咖啡:
if $('.loading').length > 0
setInterval (=>
@refreshListPartial()
), 5000
@refreshListPartial 是一个 AJAX 函数,它访问 Rails 控制器,然后继续刷新整个列表部分:
$("#list").html("<%= escape_javascript(render partial: 'status_list', locals: { list_items: @list_items } ) %>");
但是要如何检查页面上individual 列表项的状态并仅刷新它们呢?我知道 React 可能是完成这项任务的一个更简单的解决方案,但是否有可能使用 Rails 完成而不用跳过十几个圈?想到的另一件事是ActionCable(我使用的是 Rails 5),但为此功能打开永久连接似乎有点过头了,我更喜欢轮询。
更新
只是大声思考。因此,要刷新多个部分而不是一个,我需要在我的 .js.erb 文件中找到它:
<%- @items.each do |item| %>
$("#list-item-<%= item.id %>").html("<%= escape_javascript(render partial: 'item', locals: { list_item: item } ) %>");
<% end %>
视图现在应该如下所示:
ul#list
@list_items.each do |item|
== render 'list_item', list_item: @list_item
剩下的是 ajax 函数,它应该获取需要刷新的列表项的 id,并将它们作为数组发送到控制器。
【问题讨论】:
-
我猜 ActionCable 将是一个更好的选择,因为它在 Rails 5 中很容易实现。但这仍然取决于您的网站在任何时间点有多少活跃用户,因为 DB 将占用那么多命中。如果您仍然喜欢轮询,您可以运行一个计时器来检查状态,然后相应地更新视图,然后清除计时器。
-
我不认为轮询每个状态都是一个好主意。这是否意味着如果您有 5 个列表项和 5 个活动用户,您的服务器会收到大约 25 个请求?最好在活动页面中使用计时器进行轮询,并将整个列表的更改存储在服务中或绑定到每个列表项的内容中,或者使用 ActionCable。您可以让 react 或您的前端框架负责更新每个状态。
标签: javascript jquery ruby-on-rails ajax ruby-on-rails-5