It is possible. XHRs have a progress
event. The only problem is accessing the XHR object - unfortunately beforeSend
only receives the jqXHR
object and not the underlying XHR object. It is also not accessible as a property of the wrapper. You can however hook into the creation process of the XHR object by adding the following option to $.ajax()
:
xhr: function () {
var xhr = $.ajaxSettings.xhr(); // call the original function
xhr.addEventListener('progress', function (e) {
if (e.lengthComputable) {
var percentComplete = e.loaded / e.total;
// Do something with download progress
}
}, false);
return xhr;
}
Here's my initial solution. It is extremely hard to combine with jQuery since you can't easily hook into the onreadystatechange handler and cannot safely replace it after it has been set:
You need to add a custom onreadystatechange
handler. When the readyState
of the XHR object becomes 2
(*HEADERS_RECEIVED*) you can access the Content-Length
header to get the total size and then wait for the event to fire with xhr.readyState == 3
(LOADING).
Then you can calculate the progress by looking at xhr.responseText.length
.
However, this will only fire once. So you need to start a timer (using setInterval()
) which will check the ready state and response size e.g. every 100 msecs. As soon as the request finishes you stop the interval again using clearInterval()
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…