A carga é igual a readyState == 4 no XMLHttpRequest?

122

Estou confuso sobre o evento de retorno xhr, como posso dizer, não há muito diferente entre onreadystatechange -> readyState == 4 e onload, é verdade?

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

xhr.send(null);

ou

xhr.onload = function() { /* do something */ }
Huang
fonte
13
Se alguém estiver olhando para isso como um exemplo, observe que está usando async = false (terceiro argumento de xhr.open) - que normalmente não é o que você deseja.
Eddiewould5 /

Respostas:

65

Deve ser a mesma coisa. onloadfoi adicionado no XMLHttpRequest 2, enquanto onreadystatechangeexiste desde a especificação original.

JK
fonte
Parece que o Safari móvel não volta ao usar o onload. uma mudança de estatísticas funciona, no entanto.
Kai Hartmann
1
Não há mais uma separação clara e real entre XHR 1 e XHR 2, eles se fundiram em um padrão. O recurso mais comum que representa o XHR 2 é o suporte ao CORS, portanto, desse ponto de vista, o XHR 2 não apareceu no IE até o IE 10, mas o XHR.onload foi suportado no IE 9, que geralmente é considerado XHR 1.
Chase
153

Isso quase sempre é verdade. Uma diferença significativa, no entanto, é que o onreadystatechangemanipulador de eventos também é acionado readyState==4nos casos em que o onerrormanipulador geralmente é acionado (geralmente um problema de conectividade de rede). Ele obtém o status 0 neste caso. Eu verifiquei que isso acontece no Chrome, Firefox e IE mais recente.

Portanto, se você estiver usando onerrore estiver direcionando navegadores modernos, não deve usá-lo, onreadystatechangemas deve usá-lo onload, o que parece ter garantia de ser chamado somente quando a solicitação HTTP for concluída com êxito (com uma resposta real e um código de status). Caso contrário, você poderá obter dois manipuladores de eventos acionados em caso de erros (que é como eu descobri empiricamente esse caso especial).

Aqui está um link para um programa de teste do Plunker que escrevi que permite testar diferentes URLs e ver a sequência real de eventos e readyStatevalores, conforme visto pelo aplicativo JavaScript em diferentes casos. O código JS também está listado abaixo:

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 Echeverria
fonte
2
@Fernando Para esclarecer, por dentro onload, readyState === 4é garantido que é verdade, certo?
kgf3JfUtW
6
@ sam Sim, isso parece sempre ser o caso, embora o oposto não seja claramente verdadeiro, como readyStatepode ser 4 errorou abortcasos também. Esse estado basicamente significa que o processo de carregamento foi concluído, com ou sem êxito. Para uma carga normal e bem-sucedida, a sequência final de eventos é: progress(com todos os dados carregados), readystatechange(com readyState == 4) load,, loadend.
Fernando Echeverria
2
Tenha em mente que onloadtambém não será desencadeada seNo 'Access-Control-Allow-Origin' header is present on the requested resource.
deathangel908
Isso é verdade. Esse é um dos casos que aciona o onerrormanipulador.
Fernando Echeverria
1
@Pacerier: Sim, por favor veja aqui: teste plnkr
Fernando Echeverria
10

Não, eles não são os mesmos. Se você encontrar um erro de rede ou interromper a operação, onloadnão será chamado. Na verdade, o evento mais próximo readyState === 4seria loadend. O fluxo fica assim:

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
do utilizador
fonte