What is the cleanest way to get jQuery ajax request progress?

In simple javascript, it’s very simple: you just need to attach the callback to {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 am making an ajax site that loads html data using jQuery ( $.get() or $.ajax() ), and I was wondering which one is the best way to get the request flow in order to display it with a little but curious I find nothing useful in jQuery documentation ...

+90
javascript jquery ajax
01 Oct '13 at 22:21
source share
5 answers

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

 $.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 } }); 
+130
01 Oct '13 at 22:27
source share

jQuery has already implemented promises, so it's better to use this technology and not translate the event logic into options . I created a jQuery plugin that adds perspectives to progress, and now it is easy to use, like other promises:

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

Check it out on github

+38
Aug 28 '15 at 13:50
source share

jQuery has an AjaxSetup() function that allows you to register global ajax handlers such as beforeSend and complete for all ajax calls and also allow access to the xhr object to achieve the progress you are looking for

+5
01 Oct '13 at 22:26
source share

I tried three different ways to intercept the construction of an Ajax object:

  • My first attempt used xhrFields , but this only allows one listener, only attaches to the load (does not load), and requires what seems like unnecessary copy and paste.
  • My second attempt attached the progress function to the returned promise, but I had to maintain my own array of handlers. I could not find a good object for attaching handlers, because in one place I could access XHR and the other I would have access to jQuery XHR, but I never had access to the deferred object (only its promise).
  • My third attempt gave me direct access to XHR to bind handlers, but again required a lot of code to copy and paste.
  • I wrapped my third attempt and replaced jQuery ajax with my own. The only potential downside is that you can no longer use your own xhr() parameter. You can enable this by checking to see if there is an options.xhr function.

I really call my promise.progress function promise.progress , so I can easily find it later. You might want to call this something else to separate download and download listeners. Hope this helps someone, even if the original poster has already received what it needs.

 (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); 
+5
Feb 03 '14 at 17:58
source share

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

I searched for a similar solution and found that it is being used fully.

 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 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'); 
-one
Aug 16 '15 at 8:12
source share



All Articles