获取JQuery ajax请求进展的最简洁方法是什么?

gua*_*ari 90 javascript ajax jquery xmlhttprequest

在普通的javascript中非常简单:只需将回调附加到 {XMLHTTPRequest}.onprogress

var xhr = new XMLHttpRequest();

xhr.onprogress = function(e){
    if (e.lengthComputable)
        var percent = (e.loaded / e.total) * 100;
};

xhr.open('GET', 'http://www...', true);
xhr.onreadystatechange = function() {
    ...
};
xhr.send(null);
Run Code Online (Sandbox Code Playgroud)

但我正在做一个用JQuery($.get()$.ajax())下载html数据的ajax网站,我想知道哪个是获取请求进度的最佳方式,以便用一点进度条显示它,但奇怪的是,我不是在JQuery文档中找到任何有用的东西......

mat*_*mmo 130

像这样的东西$.ajax(虽然HTML5):

$.ajax({
    xhr: function() {
        var xhr = new window.XMLHttpRequest();
        xhr.upload.addEventListener("progress", function(evt) {
            if (evt.lengthComputable) {
                var percentComplete = evt.loaded / evt.total;
                //Do something with upload progress here
            }
       }, false);

       xhr.addEventListener("progress", function(evt) {
           if (evt.lengthComputable) {
               var percentComplete = evt.loaded / evt.total;
               //Do something with download progress
           }
       }, false);

       return xhr;
    },
    type: 'POST',
    url: "/",
    data: {},
    success: function(data){
        //Do something on success
    }
});
Run Code Online (Sandbox Code Playgroud)

  • HTTP 响应头告诉我们期望多少字节,这个进度只是计算到目前为止已经接收了多少字节。它将保持为零,直到实际发送 HTTP 响应 (2认同)
  • 它只能在POST上运行,不能同时在GET和其他程序上运行吗? (2认同)

lik*_*rRr 39

jQuery已经实现了promises,因此最好使用这种技术,而不是将事件逻辑移动到options参数.我制作了一个jQuery插件,增加了进步承诺,现在它像其他承诺一样易于使用:

$.ajax(url)
  .progress(function(){
    /* do some actions */
  })
  .progressUpload(function(){
    /* do something on uploading */
  });
Run Code Online (Sandbox Code Playgroud)

github上查看

  • 我收到错误消息:`TypeError:$ .ajax(...)。progress(...)。progressUpload不是函数`....这是什么问题? (3认同)
  • 有效且优雅的解决方案,但您可能知道它可能会破坏您现有的代码,因为它会破坏对已弃用的 .success 和 .error 的所有调用。它还删除您在 jqXHR 对象上设置的所有非标准属性。它也没有为 uploadProgress 回调提供“this”的上下文(可能与进度相同但未测试),因为它是为 jqXHR 的所有标准承诺完成的。所以你需要在闭包中传递上下文。 (2认同)

Kev*_*Pei 5

jQuery有一个AjaxSetup()函数,允许您注册全局ajax处理程序,例如beforeSendcomplete所有ajax调用,以及允许您访问xhr对象以执行您要查找的进度

  • 还有一个回答这个问题的例子?我担心我无法提出一个让我做大量小提琴和阅读的答案,特别是当链接页面没有提及任何进展时.老实说,我对此持怀疑态度,特别是考虑到该页面上的警告,说"注意:全局回调函数应该使用各自的全局Ajax事件处理程序方法设置--`.ajaxStart()`,`.ajaxStop()` ,`.ajaxComplete()`,`.ajaxError()`,`.ajaxSuccess()`,`.ajaxSend()` - 而不是`$ .ajaxSetup()`的选项对象.<http://api.jquery.com/jQuery.ajaxSetup/#entry-longdesc> (6认同)
  • [来自文档](https://api.jquery.com/jQuery.ajaxSetup/):_为将来的 Ajax 请求设置默认值。不建议使用它。_ (3认同)
  • 谢谢你的链接.你能在答案中加入一个例子吗? (2认同)

Mar*_*ung 5

我尝试了三种不同的方法来拦截Ajax对象的构造:

  1. 我的第一次尝试使用xhrFields,但是仅允许一个侦听器,仅附加下载(而不是上传)进度,并且需要看起来不必要的复制粘贴。
  2. 我的第二次尝试将一个progress函数附加到返回的Promise,但是我必须维护自己的处理程序数组。我找不到合适的对象来附加处理程序,因为我可以访问XHR的另一个地方,可以访问jQuery XHR的地方,但是我从来没有访问延迟的对象(只有它的Promise)。
  3. 我的第三次尝试使我可以直接访问XHR以附加处理程序,但又需要大量的复制和粘贴代码。
  4. 我结束了第三次尝试,并用ajax自己的方法替换了jQuery 。唯一的潜在缺点是您无法再使用自己的xhr()设置。您可以通过检查是否options.xhr为函数来实现这一点。

我实际上调用了我的promise.progress函数,xhrProgress以便以后可以轻松找到它。您可能需要命名其他名称来分隔上载和下载侦听器。我希望这对某人有帮助,即使原始海报已经得到了他所需要的。

(function extend_jQuery_ajax_with_progress( window, jQuery, undefined )
{
var $originalAjax = jQuery.ajax;
jQuery.ajax = function( url, options )
{
    if( typeof( url ) === 'object' )
    {options = url;url = undefined;}
    options = options || {};

    // Instantiate our own.
    var xmlHttpReq = $.ajaxSettings.xhr();
    // Make it use our own.
    options.xhr = function()
    {return( xmlHttpReq );};

    var $newDeferred = $.Deferred();
    var $oldPromise = $originalAjax( url, options )
    .done( function done_wrapper( response, text_status, jqXHR )
    {return( $newDeferred.resolveWith( this, arguments ));})
    .fail( function fail_wrapper( jqXHR, text_status, error )
    {return( $newDeferred.rejectWith( this, arguments ));})
    .progress( function progress_wrapper()
    {
        window.console.warn( "Whoa, jQuery started actually using deferred progress to report Ajax progress!" );
        return( $newDeferred.notifyWith( this, arguments ));
    });

    var $newPromise = $newDeferred.promise();
    // Extend our own.
    $newPromise.progress = function( handler )
    {
        xmlHttpReq.addEventListener( 'progress', function download_progress( evt )
        {
            //window.console.debug( "download_progress", evt );
            handler.apply( this, [evt]);
        }, false );
        xmlHttpReq.upload.addEventListener( 'progress', function upload_progress( evt )
        {
            //window.console.debug( "upload_progress", evt );
            handler.apply( this, [evt]);
        }, false );
        return( this );
    };
    return( $newPromise );
};
})( window, jQuery );
Run Code Online (Sandbox Code Playgroud)