首页 > 解决方案 > 频繁刷新 div 而不在 Rails 中刷新页面

问题描述

我有一个 rails 应用程序,它显示了我系统的 CPU 使用率、总内存、正常运行时间等详细信息。

我希望它使用 AJAX 每 0.25 秒更新一次字段。我的 index_controller.rb 有这一行:

class IndexController < ApplicationController
    def system_stats
    end
end

system_stats.html.erb:

<div class="centrify mb-4">
    <div class="logo">
        <svg class="pi-anim" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#00c1fd" d="M256 512A254 254 0 010 256 254 254 0 01256 0a254 254 0 01256 256 254 254 0 01-256 256z" data-original="#00C1FD"/><path fill="#08a8ee" d="M437 75C389 27 324 0 256 0v512a254 254 0 00256-256c0-68-27-133-75-181z" data-original="#08A8EE"/><g fill="#e4f7ff"><path class="info-i" d="M301 371V221H191v30h20v120h-21v30h130v-30zM256 191a45 45 0 100-90 45 45 0 000 90z" data-original="#E4F7FF"/></g><path class="info-i2" fill="#cbedfd" d="M256 191a45 45 0 000-90v90zM301 371V221h-45v180h64v-30z" class="active-path" data-old_color="#CBEDFD" data-original="#CBEDFD"/></svg>
    </div>

    <h1>System Stats</h1>
</div>

<% if Rails.env.production? %>
    <div class="centrify"><h6>Warning! On a Production Server this could mean nothing</h6></div>
    <hr>
<% end %>

<h4>Processor</h4>
<%= processor[0] %>
<%= "[ #{processor[1]} ]" %>
<hr>

<h4>CPU Usages</h4>
<%= %Q[#{cpu_usage.then { |x| "Total: #{x[0]}<br>[#{x.drop(1).join(', ')}]" }}].html_safe %>
<hr>

<h4>Memory</h4>
<%= "Total: #{memory} GiB" %>
<hr>

<h4>Uptime</h4>
<div id="uptime"><%= render 'stats/uptime', remote: true %></div>
<hr>

统计/_uptime.html.erb:

<%= "Uptime: #{uptime.map { |x| x.then { |y| y < 10 ? "0#{y}" : "#{y}" }}.join(?:)}" %>

index_helper.rb:

module IndexHelper
    def processor
        if File.readable?('/proc/cpuinfo')
            cpuinfo = IO.readlines('/proc/cpuinfo')
            model = cpuinfo.select { |x| x[/\Amodel\sname/] }
            [model[0].split(?:)[1].strip, model.count]
        else
            []
        end
    end

    def cpu_usage
        if File.readable?('/proc/stat')
            data = IO.readlines('/proc/stat').select! { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
            Kernel.sleep(0.075)
            prev_data = IO.readlines('/proc/stat').select! { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }

            data.size.times.map do |x|
                %w(user nice sys idle iowait irq softirq steal).each_with_index { |el, ind| binding.eval("@#{el}, @prev_#{el} = #{data[x][ind + 1]}, #{prev_data[x][ind + 1]}") }

                previdle, idle = @prev_idle + @prev_iowait, @idle + @iowait
                totald = idle + (@user + @nice + @sys + @irq + @softirq + @steal) -
                    (previdle + (@prev_user + @prev_nice + @prev_sys + @prev_irq + @prev_softirq + @prev_steal))
                "#{((totald - (idle - previdle)) / totald * 100).round( x == 0 ? 2 : 0 ).then { |y| y.to_s == 'NaN' ? 0 : y }.abs}%"
            end
        else
            ''
        end
    end

    def memory
        if File.readable?('/proc/meminfo')
            meminfo = IO.readlines('/proc/meminfo')
            meminfo.find { |x| x[/^MemTotal/] }.split[1].to_i.fdiv(1024 ** 2).round(2)
        else
            0
        end
    end

    def uptime
        if File.readable?('/proc/uptime')
            uptime = IO.read('/proc/uptime').split[0].to_i
            [uptime / 3600, uptime % 3600 / 60, uptime % 60]
        else
            []
        end
    end
end

这可行,但为了简单起见,我想每 0.25 秒更新一次正常运行时间 div,这样做的方法是什么?我已经安装并运行了 JQuery。

标签: ruby-on-rails

解决方案


创建一个函数以每 0.25 秒执行一次 AJAX 请求:

function updateSystemInfo() {
  setInterval(function(){ 
    Rails.ajax({
      url: "/system_stats",
      type: "get",
      dataType: "script"
    });
 }, 0250);
}

现在你的控制器想要响应 JS 请求并寻找一个system_stats.js.erb文件。在该文件中,您可以告诉 rails 更新您要更新的视图部分。

现在您可以将以下部分放入 partial _system_stats.html.erb

<h4>Processor</h4>
<%= processor[0] %>
<%= "[ #{processor[1]} ]" %>
<hr>

<h4>CPU Usages</h4>
<%= %Q[#{cpu_usage.then { |x| "Total: #{x[0]}<br>[#{x.drop(1).join(', ')}]" }}].html_safe %>
<hr>

<h4>Memory</h4>
<%= "Total: #{memory} GiB" %>
<hr>

然后在上面system_stats.html.erb放置一个带有 ID 的空 div,例如<div id="system_stats"></div>

现在在system_stats.js.erb你告诉rails 用ID system_stats 渲染div 中的部分。

$("#system_stats").html("#{escape_javascript(render 'system_stats')}");

现在每 0.25 秒将重新渲染部分。


推荐阅读