什么是最简洁的方式来获得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处理程序,如beforeSend
并complete
所有的ajax调用,并允许你访问xhr
对象来完成你正在寻找的进度
我尝试了三种拦截Ajax对象构造的方法:
- 我第一次尝试使用
xhrFields
,但只允许一个监听器,只附加下载(不上传)的进度,并要求什么似乎是不必要的复制和粘贴。 - 我第二次尝试在返回的承诺中附加了
progress
函数,但是我必须维护自己的处理程序数组。 我无法find一个好的对象来附加处理程序,因为一个地方我可以访问XHR,另一个我可以访问jQuery XHR,但我从来没有访问过延迟对象(只有它的承诺)。 - 我的第三次尝试让我直接访问XHR来附加处理程序,但又需要复制和粘贴代码。
- 我结束了第三次尝试,用我自己的代替了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');