获取 JQuery ajax 请求进度的最干净方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19126994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 23:14:15  来源:igfitidea点击:

What is the cleanest way to get the progress of JQuery ajax request?

javascriptajaxjqueryxmlhttprequest

提问by guari

In plain javascript is very simple: need just to attach the callback to {XMLHTTPRequest}.onprogress

在普通的 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);

but I'm doing an ajax site that download html data with JQuery ($.get()or $.ajax()) and I was wondering which is the best way to get the progress of a request in order to display it with a little progress bar but curiously, I'm not finding anything usefull in JQuery documentation...

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

回答by mattytommo

Something like this for $.ajax(HTML5 only though):

像这样的东西$.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
    }
});

回答by likerRr

jQuery has already implemented promises, so it's better to use this technology and not move events logic to optionsparameter. I made a jQuery plugin that adds progress promise and now it's easy to use just as other promises:

jQuery 已经实现了 promises,所以最好使用这种技术,而不是将事件逻辑移到options参数上。我制作了一个 jQuery 插件,它添加了进度承诺,现在它就像其他承诺一样易于使用:

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

Check it out at github

github 上查看

回答by MarkMYoung

I tried about three different ways of intercepting the construction of the Ajax object:

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

  1. My first attempt used xhrFields, but that only allows for one listener, only attaches to download (not upload) progress, and requires what seems like unnecessary copy-and-paste.
  2. My second attempt attached a progressfunction to the returned promise, but I had to maintain my own array of handlers. I could not find a good object to attach the handlers because one place I'd access to the XHR and another I'd have access to the jQuery XHR, but I never had access to the deferred object (only its promise).
  3. My third attempt gave me direct access to the XHR for attaching handlers, but again required to much copy-and-paste code.
  4. I wrapped up my third attempt and replaced jQuery's ajaxwith my own. The only potential shortcoming is you can no longer use your own xhr()setting. You can allow for that by checking to see whether options.xhris a function.
  1. 我第一次尝试使用xhrFields,但只允许一个听众,只附加下载(而不是上传)进度,并且需要看起来不必要的复制和粘贴。
  2. 我的第二次尝试将一个progress函数附加到返回的 Promise,但我必须维护自己的处理程序数组。我找不到一个好的对象来附加处理程序,因为一个地方我可以访问 XHR,另一个地方我可以访问 jQuery XHR,但我从来没有访问过延迟对象(只有它的承诺)。
  3. 我的第三次尝试让我可以直接访问 XHR 以附加处理程序,但同样需要大量的复制和粘贴代码。
  4. 我结束了第三次尝试并ajax用我自己的替换了 jQuery 。唯一潜在的缺点是您不能再使用自己的xhr()设置。您可以通过检查是否options.xhr为函数来允许这样做。

I actually call my promise.progressfunction xhrProgressso I can easily find it later. You might want to name it something else to separate your upload and download listeners. I hope this helps someone even if the original poster already got what he needed.

我实际上调用了我的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 );

回答by Kevin Pei

jQuery has an AjaxSetup()function that allows you to register global ajax handlers such as beforeSendand completefor all ajax calls as well as allow you to access the xhrobject to do the progress that you are looking for

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

回答by Sri Nair

http://www.htmlgoodies.com/beyond/php/show-progress-report-for-long-running-php-scripts.html

http://www.htmlgoodies.com/beyond/php/show-progress-report-for-long-running-php-scripts.html

I was searching for a similar solution and found this one use full.

我正在寻找类似的解决方案,并发现该解决方案已被充分利用。

var es;

function startTask() {
    es = new EventSource('yourphpfile.php');

//a message is received
es.addEventListener('message', function(e) {
    var result = JSON.parse( e.data );

    console.log(result.message);       

    if(e.lastEventId == 'CLOSE') {
        console.log('closed');
        es.close();
        var pBar = document.getElementById('progressor');
        pBar.value = pBar.max; //max out the progress bar
    }
    else {

        console.log(response); //your progress bar action
    }
});

es.addEventListener('error', function(e) {
    console.log('error');
    es.close();
});

}

}

and your server outputs

和你的服务器输出

header('Content-Type: text/event-stream');
// recommended to prevent caching of event data.
header('Cache-Control: no-cache'); 

function send_message($id, $message, $progress) {
    $d = array('message' => $message , 'progress' => $progress); //prepare json

    echo "id: $id" . PHP_EOL;
    echo "data: " . json_encode($d) . PHP_EOL;
    echo PHP_EOL;

   ob_flush();
   flush();
}


//LONG RUNNING TASK
 for($i = 1; $i <= 10; $i++) {
    send_message($i, 'on iteration ' . $i . ' of 10' , $i*10); 

    sleep(1);
 }

send_message('CLOSE', 'Process complete');

回答by Rahul Gupta

Follow the steps to display Progress of Ajax Request:

按照步骤显示 Ajax 请求的进度:

  1. Create a Spinner using Html & CSS or use Bootstrap Spinner.
  2. Display the Spinner when the end-user is requesting for the AJAX Data for infinite loop or for threshold limit time.
  3. So, after a SUCCESS / ERROR result of AJAX Request, remove the Spinner which is currently displayed and show your results.
  1. 使用 Html 和 CSS 创建 Spinner 或使用 Bootstrap Spinner。
  2. 当最终用户为无限循环或阈值限制时间请求 AJAX 数据时显示 Spinner。
  3. 因此,在 AJAX 请求的 SUCCESS / ERROR 结果之后,移除当前显示的 Spinner 并显示您的结果。

To make it easy I recommend you using JS Classes for dynamically Displaying & Hiding the spinner for this purpose.

为方便起见,我建议您为此使用 JS 类来动态显示和隐藏微调器。

I Hope this helps!

我希望这有帮助!