XmlHttpRequest.onload未调用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XmlHttpRequest.onload未调用相关的知识,希望对你有一定的参考价值。

我正在玩这个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片段使用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.DONEDONE的值为4,这是我在日志中可以看到的。因此,如果这是一个与XSS相关的问题,并且浏览器阻止我连接到另一个域,那么为什么要进行实际连接并收到DONE状态?

PS:是的,我知道有很强大的库可以很容易地做到这一点,但我仍然是一个javascript菜鸟,所以我想首先了解低级别。


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


更新2: 在Firefox中再次测试,现在它可以工作。可能旧的页面仍然被缓存,这就是为什么我不能立刻注意到它。在IE8中仍然失败,我将尝试在更新的版本中测试它。

答案

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

我将URL更改为同一域中的另一个URL,现在它可以在Firefox中运行(在一些与缓存相关的错误尝试之后)和Chrome中。它仍然无法在IE8中工作,尽管official docs说它得到了支持。我发现this SO answer说不然。看起来onload函数是一种更现代的便捷方法,而检查结果的旧方法是使用onreadystatechange代替。

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

另一答案

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() 回调功能

Feign调用异常org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET&#(代

iOS 7.1 iPod 第 5 代请求信标状态和测距未发生

Java垃圾回收机制(未掌握)

Flink未解决 FLink 写 hive MemoryManager New Memory allocation smaller than the minimum allocation size(代

在 WPF 的子线程中捕获未处理的异常