【问题标题】:Get progress of AJAX call to get JSON in Rails获取 AJAX 调用的进度以在 Rails 中获取 JSON
【发布时间】:2016-10-05 12:30:00
【问题描述】:

我有以下 JS 从 Rails 应用程序中的控制器方法检索一些 JSON 数据:

$.ajax({
    xhr: function() {
        var xhr = $.ajaxSettings.xhr();
        xhr.onprogress = function(e) {
            if (e.lengthComputable) {
                console.log(e.loaded / e.total);
            }
        };
        xhr.upload.onprogress = function(e) {
            if (e.lengthComputable) {
                console.log(e.loaded / e.total);
            }
        };
        return xhr;
    },
    cache: false,
    url: '/get_data',
    method: 'GET',
    dataType: 'JSON',
    success: function(data) {
        console.log(data);
    }
});

方法如下:

def get_data
  @data = [{....}]
  respond_to do |format|
    format.html
    format.json do
      response.headers['Content-Length'] = @data.to_s.length.to_s
      render json: @data
    end
  end
end

由于@data 很大或需要先进行复杂计算,因此该方法最多可能需要 3-4 秒才能返回,因此我想在 AJAX 发生时显示进度条。

注意:我不只是想显示一个加载器,显示在 AJAX 之前和之后,而是实际显示进度!

但是我发现lengthComputable 总是错误的......

如何让 Rails 发回正确的进度?我添加了 Content-Length 标头,但它从未出现在响应中...

【问题讨论】:

    标签: javascript jquery ruby-on-rails json ajax


    【解决方案1】:

    我错了。这不是一个真正的进度条,但想法是这样的:

    $(function() {
      var pg = 0;
    
      function progressbarAdd(){
        pg++;
        $('#bar').progressbar('option', 'value', pg).children('.ui-progressbar-value').css('display', 'block'); 
      }
      
      $('#bar').progressbar({ value: 0 });
      
      $(document).on({
        ajaxStart: function(){
          timer = setInterval(function(){ 
            progressbarAdd()
          }, 100);
        },
        ajaxStop: function(){
          clearTimeout(timer);  
          $('#bar').progressbar('option', 'value', 100);
        }    
      });
      
                    
      $.ajax({
        method: 'GET',
        url:'https://viacep.com.br/ws/01001000/json/',
        dataType: 'json',
        success: function() {
          console.log('JSON:', arguments[0]);
        },
        error: function() {
          console.log('Fail');
        }
      });
    });
    <!DOCTYPE html>
    <html>
        <head>
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
            <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
            <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/black-tie/jquery-ui.css" />
        </head>
        <body>
            <div id="bar"></div>
        </body>
    </html>

    【讨论】:

    • 尽管它是伪造的,但效果非常好。除非我能让 Rails 返回真正的进度,否则我暂时会这样做。谢谢。 +1
    【解决方案2】:

    ProgressEvent.lengthComputable 只读属性是一个布尔标志,指示 ProgressEvent 所涉及的资源是否具有可以计算的长度。

    意味着它需要一个content-length 标头...才能知道资源有多大。您可能正在做的是发送一个不知道大小的应用程序八位字节流

    【讨论】:

    • 那么我有两个问题:1.) 在请求完成之前,JS 如何知道内容长度。因为只有在获得完整响应后才能得到这个。 2.) 我怎样才能让 rails 把这个寄回去?
    • 不正确。当它开始下载资源时,您首先获得标题。 xhr 有 5 个阶段:0 UNSET,1 OPENED,2 HEADERS_RECEIVED,3 LOADING,4 DONE
    • 对不起,我对rails一无所知
    • JSON 数据通常很小,下载只需一秒钟,因此计算您下载的长度/字节可能毫无意义。您可能遇到的是一个缓慢的后端,其中客户端在请求和响应之间处于空闲状态,而服务器必须从数据库中获取某些内容。所以你可能只是向客户展示一个微调器,直到它完成
    • 可能是这样的? response.headers['Content-Length'] = 1000
    【解决方案3】:

    使用 jQuery 知道请求何时完成。

    $(document).on({
        ajaxStart: function(){
            //show or create the progress bar
        },
        ajaxStop: function(){
            //hide or remove the progress bar
        }    
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-21
      • 2014-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 2020-04-04
      • 2013-07-19
      相关资源
      最近更新 更多