【问题标题】:onreadystatechange() missing on XMLHttpRequest objects [closed]XMLHttpRequest 对象上缺少 onreadystatechange() [关闭]
【发布时间】:2013-04-05 13:44:02
【问题描述】:
(function (send) {

     XMLHttpRequest.prototype.send = function () {

         console.log(this.onreadystatechange); //null
         send.apply(this, arguments);
     };

})(XMLHttpRequest.prototype.send);

为什么this.onreadystatechange 为空?根据this,它应该存在并且类型为function

【问题讨论】:

  • 它是 null 而不是 undefined(或引发未定义的异常)这一事实应该解释一下 - 它只是尚未设置。
  • 该函数只是用一些日志记录包装了send 方法。当调用 send 时,我们不知道为什么函数是 null,因为您没有向我们展示使用它的代码。

标签: javascript ajax xmlhttprequest


【解决方案1】:

onreadystatechange 确实存在...这就是为什么它是null。如果它不存在,它将是undefined。这一切都取决于它是否已经设置。它显然已经是一个属性,因为它是 null...如果不是,它将是 undefined...或者至少 "onreadystatechange" in this 将是 false

这是一个例子:

var a = new XMLHttpRequest();
a.onreadystatechange = function () {
};
a.send();

您的控制台将记录function

如果你有:

var b = new XMLHttpRequest();
b.send();

您的控制台将记录 null

这里有一个演示http://jsfiddle.net/3XKx7/

(我清楚地省略了发送 AJAX 请求的其他步骤,只是为了解释)

我并不是要暗示nullundefined 之间存在关系——我只是说当创建一个新的XMLHttpRequest 时,onreadystatechange 将在内部设置为null。是否将其设置为函数取决于您。

更新

创建/发送 XHR 的正常方式是以下顺序:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {    // This and `open` could be flip-flopped
    // whatever
};
xhr.open("POST", url, true);
xhr.send("data=data");

我总是被告知/显示创建新的XMLHttpRequest,然后是设置onreadystatechange 和调用open 的任何顺序,但只有在这两个之后我才应该调用send

所以,如果一直这样做,onreadystatechange(如果实际设置)将不是null,而是function

既然您提到您使用的是 jQuery,我决定按照您的意愿覆盖 send 方法并进行 jQuery $.ajax 调用(而不是手动发送 XMLHttpRequest)来进行测试。这是我的测试 - http://jsfiddle.net/3XKx7/1/

为什么onreadystatechange 会是null 是没有意义的,因为 jQuery 必须 绑定到该事件才能知道请求何时完成及其状态。所以我决定看一下jQuery源代码。我发现他们称事物的顺序是:

xhr.open()
xhr.send()
xhr.onreadystatechange = function () {

};

这意味着当您重写 send 方法时,onreadystatechangenull,因为 jQuery 在调用 send 之前没有设置它。我不知道他们这样做的原因......可能是为了防止像你正在做的事情......但我从未听说过或看到使用这种约定。

所以你得到它作为null 的值的原因是因为jQuery 设置onreadystatechange 调用send。这意味着当您覆盖 send 并尝试访问 onreadystatechange 属性时,它尚未设置。

希望这是一个可以帮助您理解的示例:http://jsfiddle.net/dMP6q/16/

【讨论】:

  • 我正在尝试使用它来拦截 jquery ajax 调用。无法弄清楚为什么它会为空(因为 jQuery 显然正在使用它)
  • @Johan Woah,我想我明白你在说什么。是的,为什么将其设置为null 是没有意义的。这是我正在使用 jsfiddle.net/3XKx7/1 测试的内容
  • 我应该在这个问题上更清楚:/ 不过我不知道如何解决它。
  • 感谢您深入研究:) 我需要一个全局 ajax 侦听器来处理不是由我生成的 ajax 代码(在本例中为 GWT)。直到星期一才能尝试使用 GWT,所以这就是我尝试使用 jQuery 的原因。
  • 知道了。非常感谢 Ian 的详细说明。
【解决方案2】:

你应该自己设置它,当状态改变时会调用这个函数。就像其他事件处理程序一样,如document.onloadyourelement.onclick 等。

通常你会这样做

    var httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState === 4) {
              if (httpRequest.status === 200) {
                  // use httpRequest.responseText
              }
        }
    };
    httpRequest.open('GET', url);
    httpRequest.send();

【讨论】:

  • 随机问题 - 你知道为什么每个人(是的,包括我)总是使用httpRequest inside 回调吗?为什么没有人使用this?这并不重要,但我只是想知道。我认为我从未见过有人使用this,但我会在普通事件处理程序中看到它。
  • 我有时会使用这个,但我发现使用你声明的变量是正常的:你知道它是什么,而你必须知道使用它的特定回调的上下文是什么。图像的加载也是如此。
  • 确实如此。我想我只是在想在设置对像xhr.onreadystatechange = stateChange; 这样的函数(不是匿名函数)的引用时,你不能在函数中使用xhr……你必须使用this。所以对我来说,它总是使用this,因为它应该总是引用特定的请求。不管怎样,我想这不是太重要,我只是想听听你的意见。谢谢:)
猜你喜欢
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 2012-06-06
  • 2017-03-02
  • 1970-01-01
相关资源
最近更新 更多