XMLHttpRequest 中的 onload 是否等于 readyState==4?

IT技术 javascript ajax xmlhttprequest
2021-02-06 18:10:55

我对 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个回答

几乎总是正确的。然而,一个显着的区别是,在通常触发处理程序的情况下(通常是网络连接问题),onreadystatechange也会触发事件处理程序在这种情况下,它的状态为 0。我已经在最新的 Chrome、Firefox 和 IE 上验证了这种情况。readyState==4onerror

因此,如果您正在使用onerror并且针对的是现代浏览器,则不应使用onreadystatechange而应该使用onload它,这似乎可以保证仅在 HTTP 请求成功完成(具有真实响应和状态代码)时才会调用。否则,您可能最终会在出现错误时触发两个事件处理程序(这是我凭经验发现这种特殊情况的方式。)

这是我编写Plunker 测试程序的链接,可让您测试不同的 URL 并查看readyStateJavaScript 应用程序在不同情况下看到的事件和的实际序列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();
}
@sam 是的,情况似乎总是如此,尽管相反的情况显然并非如此,readyState4 onerrorabortcase 也是如此。这种状态基本上意味着加载过程已经完成,无论成功与否。对于正常、成功的加载,事件的最终序列是:(progress加载所有数据)、readystatechange(带有readyState == 4)、loadloadend
2021-03-19 18:10:55
@Pacerier:是的,请看这里:plnkr 测试
2021-03-19 18:10:55
请记住,onload如果No 'Access-Control-Allow-Origin' header is present on the requested resource.
2021-03-21 18:10:55
@Fernando 澄清一下,在里面onloadreadyState === 4保证是真的对吗?
2021-04-07 18:10:55
这是真的。这是触发onerror处理程序的情况之一
2021-04-10 18:10:55

应该是一样的。onload是在 XMLHttpRequest 2 中添加的,而onreadystatechange自原始规范以来一直存在。

似乎,使用 onload 时,移动 Safari 不会回来。不过,onreadystatechange 有效。
2021-03-29 18:10:55
XHR 1 和 XHR 2 之间不再有真正明确的区分,它们已合并为一个标准。代表 XHR 2 的最常见功能是 CORS 支持,因此从这个角度来看,XHR 2 直到 IE 10 才出现在 IE 中,但 IE 9 中支持 XHR.onload,通常被认为是 XHR 1。
2021-04-04 18:10:55

不,它们不一样。如果遇到网络错误或中止操作,onload将不会被调用。实际上,最接近的事件readyState === 4loadend流程如下所示:

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

VS

xhr.onreadystatechange = function() {
  if (xhr.readyState === 4) {
    if (this.status == 200) {

    }
    else {} // error: cross origin, http status not 200, bad connection
  }
};