Esto es casi siempre cierto. Sin embargo, una diferencia significativa es que el onreadystatechange
controlador de eventos también se activa readyState==4
en los casos en los onerror
que normalmente se activa el controlador (normalmente un problema de conectividad de red). Obtiene un estado de 0 en este caso. He verificado que esto sucede en las últimas versiones de Chrome, Firefox e IE.
Por lo tanto, si está usando onerror
y está apuntando a navegadores modernos, no debe usar, onreadystatechange
sino que debe usar onload
en su lugar, que parece estar garantizado para ser llamado solo cuando la solicitud HTTP se haya completado con éxito (con una respuesta real y un código de estado). De lo contrario, es posible que se activen dos controladores de eventos en caso de errores (que es cómo descubrí empíricamente este caso especial).
Aquí hay un enlace a un programa de prueba de Plunker que escribí que le permite probar diferentes URL y ver la secuencia real de eventos y readyState
valores tal como la ve la aplicación JavaScript en diferentes casos. El código JS también se enumera a continuación:
var xhr;
function test(url) {
xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function() { log(xhr, "readystatechange") });
xhr.addEventListener("loadstart", function(ev) { log(xhr, "loadstart", ev.loaded + " of " + ev.total) });
xhr.addEventListener("progress", function(ev) { log(xhr, "progress", ev.loaded + " of " + ev.total) });
xhr.addEventListener("abort", function() { log(xhr, "abort") });
xhr.addEventListener("error", function() { log(xhr, "error") });
xhr.addEventListener("load", function() { log(xhr, "load") });
xhr.addEventListener("timeout", function(ev) { log(xhr, "timeout", ev.loaded + " of " + ev.total) });
xhr.addEventListener("loadend", function(ev) { log(xhr, "loadend", ev.loaded + " of " + ev.total) });
xhr.open("GET", url);
xhr.send();
}
function clearLog() {
document.getElementById('log').innerHTML = '';
}
function logText(msg) {
document.getElementById('log').innerHTML += msg + "<br/>";
}
function log(xhr, evType, info) {
var evInfo = evType;
if (info)
evInfo += " - " + info ;
evInfo += " - readyState: " + xhr.readyState + ", status: " + xhr.status;
logText(evInfo);
}
function selected(radio) {
document.getElementById('url').value = radio.value;
}
function testUrl() {
clearLog();
var url = document.getElementById('url').value;
if (!url)
logText("Please select or type a URL");
else {
logText("++ Testing URL: " + url);
test(url);
}
}
function abort() {
xhr.abort();
}