未调用 XmlHttpRequest.onload
Posted
技术标签:
【中文标题】未调用 XmlHttpRequest.onload【英文标题】:XmlHttpRequest.onload not called 【发布时间】:2013-01-21 13:42:09 【问题描述】:我正在玩这个XmlHttpRequest
的东西。在一些教程和书籍中,当请求完成时调用的是onload
函数。在我的小实验中,这个函数永远不会被调用。这是我的代码:
window.onload = function()
var url = "http://www.google.com";
var request = new XMLHttpRequest();
request.onload = function()
var state = this.readyState;
var responseCode = request.status;
console.log("request.onload called. readyState: " + state + "; status: " + responseCode);
if (state == this.DONE && responseCode == 200)
var responseData = this.responseText;
alert("Success: " + responseData.length + " chars received.");
;
request.error = function(e)
console.log("request.error called. Error: " + e);
;
request.onreadystatechange = function()
console.log("request.onreadystatechange called. readyState: " + this.readyState);
;
request.open("GET", url);
request.send(null);
;
我正在上一个 Firefox 版本(今天刚刚更新)上对此进行测试。 onload
中的日志行从不打印,我在第一行设置的断点也从不命中。但是onreadystatechange
函数被调用了两次,实际上是发起了http请求。这是 firebug 的控制台显示的内容:
request.onreadystatechange called. readyState: 1
GET http://www.google.com/ 302 Found 174ms
request.onreadystatechange called. readyState: 4
NS_ERROR_FAILURE: Failure
request.send(null);
send
行中有错误。我尝试将其更改为 request.send()
,结果相同。
起初我以为这可能是浏览器试图阻止 XSS,所以我将我的 html 驱动程序页面移动到我的开发机器中的一个 Tomcat 实例,但结果是一样的。
这个函数是否保证被调用?正如我上面所说,在大多数教程中都很常见,但另一方面,在 W3C spec page 中,hello world sn-p 使用 onreadystatechange
代替:
function processData(data)
// taking care of data
function handler()
if(this.readyState == this.DONE)
if(this.status == 200 &&
this.responseXML != null &&
this.responseXML.getElementById('test').textContent)
// success!
processData(this.responseXML.getElementById('test').textContent);
return;
// something went wrong
processData(null);
var client = new XMLHttpRequest();
client.onreadystatechange = handler;
client.open("GET", "unicorn.xml");
client.send();
它检查readyState == this.DONE
。 DONE
的值为 4,这是我在日志中看到的。因此,如果这是与 XSS 相关的问题,并且浏览器阻止我连接到不同的域,那么为什么会建立实际连接并收到 DONE 状态???
PS:是的,我知道有强大的库可以轻松做到这一点,但我仍然是 javascript 菜鸟,所以我想先了解底层。
更新:
我已将 URL 更改为我的域 (localhost) 中的一个,错误消失了,但仍然没有调用 onload
函数。在 IE8 中测试并不起作用。在 Chrome 中测试并有效。怎么样?
更新 2: 在 Firefox 中再次测试,现在它可以工作了。可能旧页面仍在缓存中,所以我无法立即注意到它。在 IE8 中仍然失败,我将尝试在更新的版本中对其进行测试。
【问题讨论】:
请注意,jQuery 已经解决了这个问题。即使你不想使用它,你也可以研究它的代码。 这是工作中的 webdevs 刚刚告诉我的。我在实际项目中使用它没有问题。我应该寻找哪个源文件? jQuery 被包裹在文件中。我不建议使用缩小版,因为它更难阅读。寻找ajax
方法,如果需要,挖掘。
我直接在 git hub 上阅读。看起来它也使用 onload,但似乎代码以更好的方式处理 XSS。
将 request.open 移到 request.load 上方
【参考方案1】:
看起来确实是 XSS 问题,Firefox 阻止了 onload
调用。我仍然无法理解为什么 http 网络请求实际上正在完成,而 onreadystatechange
被 DONE
readyState 调用。
我将 URL 更改为同一域中的另一个 URL,现在它可以在 Firefox(经过一些与缓存相关的错误尝试后)和 Chrome 中工作。尽管official docs 说它受支持,但它仍然无法在 IE8 中运行。我发现this SO answer 另有说明。看起来onload
函数是一种更现代的便捷方法,而检查结果的旧方法是改用onreadystatechange
。
我想我会接受这个答案作为解决方案,除非提供更详细的答案。
【讨论】:
一直在寻找同样的问题。想知道是否有新发现。【参考方案2】:onload
处理程序不会因为另一个原因被调用,我在这里添加它只是为了对引用此页面的其他人有所帮助。
如果 HTTP 响应格式错误,onload
处理程序也不会被调用。例如,在 Content-Length
标头中通告长度为 14 的 10 字节的纯文本响应将不会调用 onload
处理程序。在开始用测试存根替换后端单元之前,我在客户端代码上浪费了数小时。
【讨论】:
【参考方案3】:IE 有不同的方法来创建 xmlhttprequest。
function createCORSRequest(method, url)
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr)
// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHTTPRequest2 objects.
xhr.open(method, url, true);
else if (typeof XDomainRequest != "undefined")
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);
else
// Otherwise, CORS is not supported by the browser.
xhr = null;
return xhr;
;
同这篇文章:https://www.html5rocks.com/en/tutorials/cors/
【讨论】:
以上是关于未调用 XmlHttpRequest.onload的主要内容,如果未能解决你的问题,请参考以下文章
在 Jest 中测试 XMLHttpRequest onload() 回调功能
未完全加载单元格时未调用 didSelectItemAtIndexPath
numberOfRowsInSection 已调用但 cellForRowAt 未调用