什么是最简洁的方式来获得JQuery AJAX请求的进展?

在普通的javascript中很简单:只需要​​将callback附加到{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); 

但我正在做一个Ajax网站下载与JQuery( $.get()$.ajax() )的HTML数据,我想知道哪一个是获取请求的进展,以显示它与一个一点进度栏,但好奇,我没有发现任何有用的JQuery文档…

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

jQuery已经实现了promise,所以最好使用这种技术,而不是将事件逻辑移动到options参数。 我做了一个jQuery插件,增加了进度许诺,现在很容易使用,就像其他的承诺一样:

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

在github上检查一下

jQuery有一个AjaxSetup()函数,允许你注册全局ajax处理程序,如beforeSendcomplete所有的ajax调用,并允许你访问xhr对象来完成你正在寻找的进度

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

  1. 我第一次尝试使用xhrFields ,但只允许一个监听器,只附加下载(不上传)的进度,并要求什么似乎是不必要的复制和粘贴。
  2. 我第二次尝试在返回的承诺中附加了progress函数,但是我必须维护自己的处理程序数组。 我无法find一个好的对象来附加处理程序,因为一个地方我可以访问XHR,另一个我可以访问jQuery XHR,但我从来没有访问过延迟对象(只有它的承诺)。
  3. 我的第三次尝试让我直接访问XHR来附加处理程序,但又需要复制和粘贴代码。
  4. 我结束了第三次尝试,用我自己的代替了jQuery的ajax 。 唯一的潜在缺点是你不能再使用你自己的xhr()设置。 你可以通过检查options.xhr是否是一个函数来做到这一点。

我实际上调用了我的xhrProgress函数xhrProgress以便稍后可以轻松地find它。 您可能想要命名它来分隔您的上传和下载侦听器。 即使原来的海报已经得到他所需要的东西,我希望这可以帮助别人。

 (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) { // Download progress xmlHttpReq.addEventListener('progress', function download_progress(evt) { // window.console.debug( "download_progress", evt ); handler.apply(this, [evt]); }, false); // Upload progress 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); 

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

我正在寻找一个类似的解决scheme,发现这个使用完整。

 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(); }); 

}

和你的服务器输出

 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');