Czy onload jest równy readyState == 4 w XMLHttpRequest?

122

Jestem zdezorientowany co do zdarzenia powrotu xhr, jak mogę powiedzieć, nie ma tak dużej różnicy między onreadystatechange -> readyState == 4 i onload, czy to prawda?

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

xhr.send(null);

lub

xhr.onload = function() { /* do something */ }
Huang
źródło
13
Jeśli ktoś patrzy na to jako przykład, zauważ, że używa async = false (trzeci argument xhr.open) - co zwykle nie jest tym, czego byś chciał.
eddiewould

Odpowiedzi:

65

Powinno być tym samym. onloadzostał dodany w XMLHttpRequest 2, podczas gdy onreadystatechangeistnieje od pierwotnej specyfikacji.

JK
źródło
Wygląda na to, że mobilne Safari nie powraca podczas korzystania z onload. onreadystatechange działa jednak.
Kai Hartmann
1
Nie ma już rzeczywistego wyraźnego podziału między XHR 1 i XHR 2, zostały one połączone w jeden standard. Najczęstszą funkcją reprezentującą XHR 2 jest obsługa CORS, więc z tego punktu widzenia XHR 2 nie pojawił się w IE aż do IE 10, ale XHR.onload był obsługiwany w IE 9, który jest zwykle uważany za XHR 1.
Chase
153

To prawie zawsze prawda. Jedną istotną różnicą jest jednak to, że onreadystatechangeprocedura obsługi zdarzeń jest również wyzwalana readyState==4w przypadkach, w których onerrorprocedura obsługi jest zwykle wyzwalana (zwykle jest to problem z łącznością sieciową). W tym przypadku otrzymuje status 0. Sprawdziłem, że dzieje się to w najnowszej przeglądarce Chrome, Firefox i IE.

Jeśli więc używasz onerrornowoczesnych przeglądarek i kierujesz ich na cel, nie powinieneś używać, onreadystatechangeale onloadzamiast tego powinieneś używać , co wydaje się gwarantować, że zostanie wywołane tylko wtedy, gdy żądanie HTTP zostanie pomyślnie zakończone (z prawdziwą odpowiedzią i kodem stanu). W przeciwnym razie możesz otrzymać dwa programy obsługi zdarzeń wyzwalane w przypadku błędów (i tak empirycznie dowiedziałem się o tym szczególnym przypadku).

Oto link do napisanego przeze mnie programu testowego Plunker , który pozwala przetestować różne adresy URL i zobaczyć rzeczywistą sekwencję zdarzeń i readyStatewartości, jaką widzi aplikacja JavaScript w różnych przypadkach. Kod JS jest również wymieniony poniżej:

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
źródło
2
@Fernando Aby wyjaśnić, wewnątrz onload, readyState === 4jest gwarancją prawdziwej prawo?
kgf3JfUtW
6
@sam Tak, wydaje się, że zawsze tak jest, chociaż wyraźnie nie jest odwrotnie, podobnie jak readyState4 włączone errorlub abortprzypadki. Ten stan zasadniczo oznacza, że ​​proces ładowania został zakończony, niezależnie od tego, czy zakończył się pomyślnie, czy nie. W przypadku normalnego, pomyślnego załadowania końcowa sekwencja zdarzeń to: progress(z załadowanymi wszystkimi danymi), readystatechange(z readyState == 4) load,, loadend.
Fernando Echeverria
2
Pamiętaj, że to onloadrównież nie uruchomi się, jeśliNo 'Access-Control-Allow-Origin' header is present on the requested resource.
deathangel908
To prawda. To jeden z przypadków, które wyzwalają program onerrorobsługi.
Fernando Echeverria
1
@Pacerier: Tak, zobacz tutaj: test plnkr
Fernando Echeverria
10

Nie, to nie to samo. Jeśli napotkasz błąd sieciowy lub przerwiesz operację, onloadnie zostanie wywołany. Właściwie najbliższym wydarzeniem readyState === 4byłoby loadend. Przepływ wygląda następująco:

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
użytkownik
źródło