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

Posted

技术标签:

【中文标题】XMLHttpRequest 中的 onload 是不是等于 readyState==4?【英文标题】:Is onload equal to readyState==4 in XMLHttpRequest?XMLHttpRequest 中的 onload 是否等于 readyState==4? 【发布时间】:2012-02-29 03:59:27 【问题描述】:

我对 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 */ 

【问题讨论】:

如果有人将此作为示例,请注意它使用的是 async=false(xhr.open 的第三个参数)——这通常不是您想要的。 【参考方案1】:

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

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

这里是我编写的Plunker test program 的链接,可让您测试不同的 URL 并查看 javascript 应用程序在不同情况下看到的实际事件序列和 readyState 值。 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();

【讨论】:

@Fernando 澄清一下,onload 内部,readyState === 4 保证是真的对吧? @sam 是的,情况似乎总是如此,尽管相反的情况显然不正确,因为readyStateerrorabort 的情况下也可以是4。这种状态基本上意味着加载过程已经完成,无论成功与否。对于正常、成功的加载,最终的事件序列是:progress(加载所有数据)、readystatechange(带有readyState == 4)、loadloadend 请记住,onload 也不会触发 No 'Access-Control-Allow-Origin' header is present on the requested resource. 确实如此。这是触发onerror 处理程序的情况之一。 @Pacerier :是的,请看这里:plnkr test【参考方案2】:

应该是一样的。 onload 是在 XMLHttpRequest 2 中添加的,而 onreadystatechange 从最初的规范就已经存在了。

【讨论】:

看来,移动版 Safari 在使用 onload 时不会回来。不过,onreadystatechange 有效。 XHR 1 和 XHR 2 之间不再有真正明确的区别,它们已合并为一个标准。代表 XHR 2 的最常见功能是 CORS 支持,因此从这个角度来看,XHR 2 直到 IE 10 才出现在 IE 中,但 XHR.onload 在 IE 9 中得到支持,通常被认为是 XHR 1。【参考方案3】:

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

     onreadystatechange
      readyState === 4
             ⇓
 onload / onerror / onabort
             ⇓
         onloadend

【讨论】:

【参考方案4】:

在这里他们是如何处理错误的简单代码

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
  
;

【讨论】:

以上是关于XMLHttpRequest 中的 onload 是不是等于 readyState==4?的主要内容,如果未能解决你的问题,请参考以下文章

XmlHttpRequest.onload未调用

在 Jest 中测试 XMLHttpRequest onload() 回调功能

XMLHttpRequest (Ajax) 错误

XMLHttpRequest接受流请求,显示图片

如何使用 XMLHttpRequest 进行 zcash rpc 调用

Ajax 两种请求方式的区别onload和onreadystatechange