Является ли onload равным 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 */ }
Huang
источник
13
Если кто-то смотрит на это как на пример, обратите внимание, что он использует async = false (3-й аргумент xhr.open), что обычно не то, что вам нужно.
eddiewould 05

Ответы:

66

Должно быть то же самое. onloadбыл добавлен в XMLHttpRequest 2, тогда как onreadystatechangeсуществовал с момента первоначальной спецификации.

JK
источник
Кажется, что мобильный Safari не возвращается при использовании onload. Однако onreadystatechange работает.
Кай Хартманн
1
Между XHR 1 и XHR 2 больше нет реального четкого разделения, они объединены в один стандарт. Наиболее распространенной функцией, представляющей XHR 2, является поддержка CORS, поэтому с этой точки зрения XHR 2 не появлялся в IE до IE 10, но XHR.onload поддерживался в IE 9, который обычно считается XHR 1.
Чейз
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
Фернандо Эчеверриа,
11

Нет, они не такие. Если вы столкнетесь с сетевой ошибкой или прервете операцию, onloadон не будет вызван. Собственно, самое близкое событие, которое readyState === 4могло бы быть loadend. Поток выглядит так:

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
пользователь
источник