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


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(xhr.open的第3个参数)-通常这不是您想要的。
eddiewould

Answers:


65

应该是同一回事。onload是在XMLHttpRequest 2中添加的,但onreadystatechange自原始规范以来就存在。


似乎,使用onload时不会返回移动Safari。但是,onreadystatechange可以工作。
凯·哈特曼2014年

1
XHR 1和XHR 2之间不再存在真正的明显区分,它们已合并为一个标准。表示XHR 2中最常见的特征是从CORS这个观点XHR 2支持所以在IE没有出现,直到IE 10但XHR.onload其通常认为是XHR 1.在IE 9支持
大通

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'5

6
@sam是的,似乎总是这样,尽管相反的说法显然不正确,例如readyState4 on errorabortcase也是如此。此状态基本上表示加载过程已完成,无论是否成功。对于一个正常的,成功的负载,事件的最终序列是:progress(带有加载的所有数据), readystatechange(有readyState == 4), ,。load loadend
费尔南多·埃切维里亚

2
请记住,onload如果以下情况也不会触发No 'Access-Control-Allow-Origin' header is present on the requested resource.
deathangel908

确实如此。这是触发onerror处理程序的情况之一。
费尔南多·埃切维里亚

1
@Pacerier:是的,请在这里查看:plnkr测试
费尔南多·埃切维里亚

10

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

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.