Чи дорівнює завантаження рівним ReadyState == 4 у XMLHttpRequest?


122

Я плутаюсь щодо події повернення xhr, як я можу сказати, між onreadystatechange -> readyState == 4 та onload не так сильно відрізняється , це правда?

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

xhr.send(null);

або

xhr.onload = function() { /* do something */ }

13
Якщо хтось дивиться на це як приклад, зауважте, що він використовує async = false (3-й аргумент xhr.open) - що зазвичай не те, що ви хочете.
eddiewould

Відповіді:


65

Це має бути те саме. onloadбуло додано в XMLHttpRequest 2, тоді як onreadystatechangeіснує вже з початкової специфікації.


Здається, що мобільний Safari не повертається при використанні onload. Хоча вжезмінна робота працює.
Кай Хартманн

1
Справжнього чіткого поділу між XHR 1 та XHR 2 вже немає, вони об'єдналися в один стандарт. Найпоширенішою особливістю, яка представляє XHR 2, є підтримка CORS, тому з цієї точки зору XHR 2 не з'являвся в IE до IE 10, але XHR.onload підтримувався в IE 9, який, як правило, вважається XHR 1.
Chase

153

Це майже завжди так. Одна з істотних відмінностей полягає в тому, що onreadystatechangeобробник подій також спрацьовує readyState==4у випадках, коли onerrorобробник зазвичай спрацьовує (як правило, проблема з підключенням до мережі). У цьому випадку він отримує статус 0. Я перевірив, що це відбувається на останніх веб-переглядачах Chrome, Firefox та IE.

Отже, якщо ви використовуєте onerrorта орієнтуєтесь на сучасні веб-переглядачі, ви не onreadystatechangeповинні використовувати, onloadа використовувати замість цього, який, схоже, може бути викликаний лише після успішного завершення запиту HTTP (з реальним кодом відповіді та статусом). В іншому випадку ви можете отримати два обробники подій, які спрацьовують у разі помилок (саме так я емпірично дізнався про цей особливий випадок.)

Ось посилання на тестову програму Plunker, яку я написав, що дозволяє тестувати різні URL-адреси та бачити фактичну послідовність подій та readyStateзначень, що їх бачить додаток JavaScript у різних випадках. Код JS також вказаний нижче:

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();
}

2
@Fernando Щоб уточнити, всередині onload, readyState === 4гарантовано, правда правда?
kgf3JfUtW

6
@sam Так, здається, завжди так, хоча навпаки явно не відповідає дійсності, як це readyStateможе бути 4 errorабо abortвипадки теж. Цей стан означає, що процес завантаження завершено, успішно чи ні. Для нормального успішного завантаження кінцевою послідовністю подій є: progress(із усіма завантаженими даними), readystatechangereadyState == 4) load,, loadend.
Фернандо Ехеверрія

2
Майте на увазі, що onloadтакож не спрацьовує, якщоNo 'Access-Control-Allow-Origin' header is present on the requested resource.
deathangel908

Це правда. Це один із випадків, коли спрацьовує onerrorобробник.
Фернандо Ехеверрія

1
@Pacerier: Так, дивіться тут: plnkr test
Fernando Echeverria

10

Ні, вони не однакові. Якщо ви зіткнулися з мережевою помилкою або перервали операцію, onloadне буде викликано. Власне, найближчою подією readyState === 4було б loadend. Потік виглядає приблизно так:

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.