Esto es casi siempre cierto. Sin embargo, una diferencia significativa es que el onreadystatechangecontrolador de eventos también se activa readyState==4en los casos en los onerrorque 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 onerrory está apuntando a navegadores modernos, no debe usar, onreadystatechangesino que debe usar onloaden 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 readyStatevalores 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();
}