¿Onload es igual a readyState == 4 en XMLHttpRequest?

122

Estoy confuso sobre el evento de retorno xhr, como puedo decir, no hay mucha diferencia entre onreadystatechange -> readyState == 4 y onload, ¿es cierto?

var xhr = new XMLHttpRequest();
xhr.open("Get", url, false);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4)
    {
        /* do some thing*/
    }
};

xhr.send(null);

o

xhr.onload = function() { /* do something */ }
Huang
fuente
13
Si alguien está viendo esto como un ejemplo, tenga en cuenta que está usando async = false (tercer argumento de xhr.open), que normalmente no es lo que desearía.
eddiewould

Respuestas:

65

Debería ser lo mismo. onloadse agregó en XMLHttpRequest 2 mientras que onreadystatechangeha existido desde la especificación original.

JK
fuente
Parece que Safari móvil no vuelve cuando se usa onload. onreadystatechange funciona, sin embargo.
Kai Hartmann
1
Ya no existe una separación clara real entre XHR 1 y XHR 2, se han fusionado en un estándar. La característica más común que representa XHR 2 es la compatibilidad con CORS, por lo que, desde ese punto de vista, XHR 2 no apareció en IE hasta IE 10, pero XHR.onload fue compatible con IE 9, que generalmente se cree que es XHR 1.
Chase
153

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();
}
Fernando Echeverría
fuente
2
@Fernando Para aclarar, por dentro onload, ¿ readyState === 4se garantiza que sea verdad?
kgf3JfUtW
6
@sam Sí, ese parece ser siempre el caso, aunque lo contrario claramente no es cierto, como readyStatepuede ser 4 en erroro abortcasos también. Este estado básicamente significa que el proceso de carga ha finalizado, ya sea con éxito o no. Para una carga normal y exitosa, la secuencia final de eventos es: progress(con todos los datos cargados), readystatechange(con readyState == 4) load,, loadend.
Fernando Echeverría
2
Tenga en cuenta que onloadtampoco se activará siNo 'Access-Control-Allow-Origin' header is present on the requested resource.
deathangel908
Es verdad. Ese es uno de los casos que desencadena el onerrorcontrolador.
Fernando Echeverría
1
@Pacerier: Sí, consulte aquí: prueba plnkr
Fernando Echeverría
10

No, no son lo mismo. Si encuentra un error de red o cancela la operación, onloadno será llamado. En realidad, el evento más cercano readyState === 4sería loadend. El flujo se ve así:

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
usuario
fuente