Javascript 未调用 XmlHttpRequest.onload

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14727710/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 17:45:07  来源:igfitidea点击:

XmlHttpRequest.onload not called

javascriptajaxfirefoxxmlhttprequest

提问by Mister Smith

I'm playing around with this XmlHttpRequestthing. In some tutorials and books, it is the onloadfunction the one that is called when the request is done. In my little experiment, this function is never called. Here's my code:

我在玩这个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);
    };

I'm testing this on the last Firefox release (just updated today). The log line in onloadis never printed, and the breakpoint I set in the first line is never hit. However, the onreadystatechangefunction is called twice, and the http request is actually made. This is what firebug's console shows:

我正在上一个 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);

There's an error in the sendline. I've tried changing it to request.send()with identical result.

send线路中有错误。我尝试将其更改为request.send()具有相同的结果。

At first I thought this might be the browser trying to prevent XSS, so I moved my html driver page to a Tomcat instance in my dev machine, but the result is the same.

起初我以为这可能是浏览器试图阻止 XSS,所以我将我的 html 驱动程序页面移动到我的开发机器中的 Tomcat 实例,但结果是一样的。

Is this function guaranteed to be called? As I've said above, it's common to be seen in most tutorials, but on the other hand in the W3C spec page, the hello world snippet uses onreadystatechangeinstead:

这个函数能保证被调用吗?正如我在上面所说的,在大多数教程中很常见,但另一方面,在W3C 规范页面中,hello world 代码段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();

It checks readyState == this.DONE. DONEhas the value 4, which is what I can see in my log. So if this were a XSS related issue, and the browser were preventing me to make the connection to a different domain, then why the actual connection is made and the DONE status is received???

它检查readyState == this.DONE. DONE具有值 4,这是我在日志中可以看到的。因此,如果这是与 XSS 相关的问题,并且浏览器阻止我连接到不同的域,那么为什么要建立实际连接并收到 DONE 状态???

PS: Yes, I know there are powerful libraries to do this easily, but I'm still a JavaScript noob so I'd like to understand the low level first.

PS:是的,我知道有强大的库可以轻松地做到这一点,但我仍然是一个 JavaScript 菜鸟,所以我想先了解底层。



UPDATE:
I've changed the URL to one inside my domain (localhost), and the error is gone but the onloadfunction is still not being called. Tested in IE8 and does not work. Tested in Chrome and works. How's that?

更新:
我已将 URL 更改为我的域 (localhost) 中的 URL,错误消失了,但onload仍未调用该函数。在 IE8 中测试过,不起作用。在 Chrome 中测试并有效。怎么样?



UPDATE 2:
Tested again in Firefox, and now it works. Probably the old page was still cached so that's why I couldn't notice it immediatly. Still failing in IE8, I'll try to test it in a newer version.

更新 2:
在 Firefox 中再次测试,现在可以使用了。可能旧页面仍然被缓存,所以这就是为什么我不能立即注意到它。在 IE8 中仍然失败,我将尝试在较新的版本中对其进行测试。

回答by Mister Smith

It looks like it was indeed a XSS issue and Firefox was blocking the onloadcall. I can't still understand why the http network request was actually being done and the onreadystatechangewas being called with the DONEreadyState.

看起来确实是 XSS 问题,Firefox 阻止了onload调用。我仍然无法理解为什么实际上已经完成了 http 网络请求并且onreadystatechange正在使用DONEreadyState调用它。

I changed the URL to another one in the same domain, and now it works in Firefox (after some cache-related false attempts) and in Chrome. It still does not work in IE8, despite the official docssay it is supported. I've found this SO answerwhich states otherwise. It looks like the onloadfunction is a more modern convenience method and the old way of checking the result is using onreadystatechangeinstead.

我将 URL 更改为同一域中的另一个 URL,现在它可以在 Firefox(经过一些与缓存相关的错误尝试之后)和 Chrome 中工作。尽管官方文档说它受支持,但它仍然无法在 IE8 中工作。我发现这个 SO answer另有说明。看起来该onload函数是一种更现代的便捷方法,onreadystatechange而是使用了旧的检查结果的方法。

I guess I'll accept this answer as the solution unless a more detailed answer is provided.

我想除非提供更详细的答案,否则我会接受这个答案作为解决方案。

回答by inter18099

IE has different method to create xmlhttprequest.

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

same this article:https://www.html5rocks.com/en/tutorials/cors/

同样这篇文章:https: //www.html5rocks.com/en/tutorials/cors/

回答by DannyNiu

The onloadhandler won't be called for yet another reason, I'm adding it here just so it can be helpful to someone else referencing this page.

onload处理器将不会被调用的另一个原因,我在这里将它只是它可以帮助别人引用此页面。

If the HTTP response is malformed, the onloadhandler will not be called either. For example, a plaintext response of 10 bytes that advertises a length of 14 in Content-Lengthheader will not invoke the onloadhandler. I wasted hours on client code before I start to replace back-end units with test stubs.

如果 HTTP 响应格式错误,onload处理程序也不会被调用。例如,在Content-Length标头中通告长度为 14 的 10 个字节的纯文本响应将不会调用onload处理程序。在开始用测试存根替换后端单元之前,我在客户端代码上浪费了几个小时。