En clair, javascript est très simple: il suffit d’attacher le rappel à {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);
mais je fais un site ajax qui télécharge des données html avec JQuery ($.get()
ou $.ajax()
) et je me demandais quel est le meilleur moyen d’obtenir la progression d’une requête afin de l’afficher avec un message. petite barre de progression mais curieusement, je ne trouve rien d’utile dans la documentation JQuery ...
Quelque chose comme ceci pour $.ajax
(HTML5 seulement):
$.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 a déjà mis en œuvre des promesses, il est donc préférable d'utiliser cette technologie et de ne pas déplacer la logique des événements vers le paramètre options
. J'ai créé un plugin jQuery qui ajoute une promesse de progrès et est maintenant facile à utiliser, tout comme les autres promesses:
$.ajax(url)
.progress(function(){
/* do some actions */
})
.progressUpload(function(){
/* do something on uploading */
});
Vérifiez-le à github
jQuery a une fonction AjaxSetup()
qui vous permet d'enregistrer des gestionnaires d'ajax globaux tels que beforeSend
et complete
pour tous les appels ajax, ainsi que d'accéder à la xhr
objet de faire le progrès que vous recherchez
J'ai essayé trois méthodes différentes pour intercepter la construction de l'objet Ajax:
xhrFields
, mais cela ne permettait qu'à un seul auditeur, ne joignait que pour télécharger (pas télécharger) la progression, et nécessite ce qui semble être un copier-coller inutile.progress
à la promesse retournée, mais je devais gérer mon propre tableau de gestionnaires. Je ne pouvais pas trouver un bon objet pour attacher les gestionnaires car un endroit aurait accès au XHR et un autre au jQuery XHR, mais je n'ai jamais eu accès à l'objet différé (seulement sa promesse).ajax
de jQuery par le mien. Le seul inconvénient potentiel est que vous ne pouvez plus utiliser votre propre réglage xhr()
. Vous pouvez le faire en vérifiant si options.xhr
est une fonction.J'appelle en fait ma fonction promise.progress
xhrProgress
afin de pouvoir la retrouver facilement plus tard. Vous voudrez peut-être lui attribuer un autre nom pour séparer votre téléchargement et télécharger les écouteurs. J'espère que cela aidera quelqu'un même si l'affiche originale a déjà obtenu ce dont il avait besoin.
(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);