Нагрузка равна readyState==4 в XMLHttpRequest?
Я запутался в событии возврата 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 */ }
4 ответа
Это должно быть то же самое. onload
был добавлен в XMLHttpRequest 2, тогда как onreadystatechange
был вокруг с оригинальной спецификации.
Это почти всегда так. Однако одно существенное отличие состоит в том, что обработчик события 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();
}
Нет, они не одинаковы. Если вы столкнулись с ошибкой в сети или прервали операцию, onload
не будет называться. На самом деле, самое близкое событие к readyState === 4
было бы loadend
, Поток выглядит так:
onreadystatechange
readyState === 4
⇓
onload / onerror / onabort
⇓
onloadend
в простом коде здесь, как они обрабатывают ошибку
xhr.onload = function() {
// same or allowed cross origin
if (this.status == 200) {
}
else {} // error http status not 200
};
xhr.onerror = function() {
//error: cross origin, bad connection
};
ПРОТИВ
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (this.status == 200) {
}
else {} // error: cross origin, http status not 200, bad connection
}
};