2012-02-07 39 views
94

我对xhr返回事件感到迷惑,正如我所知,onreadystatechange - > readyState == 4和onload之间并没有太大的区别,这是真的吗?XMLHttpRequest中的onload等于readyState == 4吗?

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 */ } 
+3

如果有人看着这个作为例子。注意,它使用异步=假(xhr.open的第三个参数) - 这是不正常你想要什么。 – eddiewould 2016-10-05 21:30:35

回答

54

它应该是同样的事情。在XMLHttpRequest 2中添加了onload,而onreadystatechange自原始规范开始出现。

+0

似乎,移动Safari在使用onload时不会回来。 onreadystatechange工程,虽然。 – 2014-01-21 14:24:03

+1

XHR 1和XHR 2之间并没有真正明确的区分,它们已经合并为一个标准。代表XHR 2的最常见功能是CORS支持,因此从该观点来看,XHR 2在IE 10之前不会出现在IE中,但XHR.onload在通常被认为是XHR 1的IE 9中受支持。 – Chase 2014-11-05 06:39:08

122

这是差不多总是如此。然而,一个显着的区别是onreadystatechange事件处理程序在onerror处理程序通常被触发(通常是网络连接问题)的情况下也会被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(); 
 
}

+4

这应该是被接受的回答:)感谢您的详细信息 – 2015-08-17 15:00:03

+2

@Fernando澄清,在'onload'中,'readyState === 4'保证是正确的吗? – sam 2017-05-01 15:30:38

+4

@sam是的,这似乎总是如此,但相反显然不是真实的,因为'readyState'也可以在'error'或'abort'情况下为4。这个状态基本上意味着加载过程已经完成,无论是否成功。对于一个正常的,成功的加载,事件的最后一个序列是:'progress'(加载所有数据),'readystatechange'('readyState == 4'),'load','loadend'。 – 2017-05-02 14:48:52

1

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

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