jQuery Ajax,覆盖onreadystatechange处理程序

时间:2010-07-22 13:13:11

标签: javascript jquery ajax

我最近在讨论一些ajax轮询技术。但是,我似乎无法覆盖FireFox(3.6.7)中onreadystatechange对象的XMLHttpRequest处理程序。

在跟踪问题时,为什么FF在尝试访问onreadystatechange时抛出异常,我意识到这取决于是否调用了send()方法。

换句话说,这是一个例子(普通的js,到目前为止没有jQuery),它有效:

(这只是为了演示而相当简化)

var myxhr = new XMLHttpRequest();
myxhr.open("GET", "/my/index.php");
myxhr.onreadystatechange = function(){
    console.log('ready state changed');
};
console.log("onreadystatechange function: ", myxhr.onreadystatechange);
myxhr.send(null);

这有效,更好地说可以在这里访问myxhr.onreadystatechange。如果我切换最后两行代码,FF会抛出一个异常,基本上告诉我我不允许访问这个对象。

myxhr.send(null);
console.log("onreadystatechange function: ", myxhr.onreadystatechange);

失败。

那我的实际问题在哪里?

好吧,我想使用jQuery的$.ajax()。但是,如果我尝试覆盖从onreadystatechange返回的XHR对象的$.ajax()方法,则会收到相同的FireFox异常。

好的,我已经找到了为什么会发生这种情况,所以我想到了,嘿beforeSend $.ajax()属性怎么样?所以我基本上试过这个:

var myxhr = $.ajax({
   url:        "/my/index.php",
   type:       "GET",
   dataType:   "text",
   data:        {
       foo:    "1"
   },
   beforeSend: function(xhr){
       var readystatehook = xhr.onreadystatechange;

       xhr.onreadystatechange = function(){
           readystatehook.apply(this, []);
           console.log('fired');
       };
   },
   success:    function(data){
       console.log(data);
   },
   error:      function(xhr, textStatus, error){
       console.log(xhr.statusText, textStatus, error);
   }
});

猜猜看,FireFox会抛出异常。那你现在做什么?你像我一样深入研究jQuery源代码。但实际上,这带来的问题多于答案。看起来beforeSend()在执行xhr.send()之前就已经被调用了。所以我想知道为什么FireFox在此时不允许覆盖处理程序。

结论

用jQuery / Firefox创建custom readystatechange handler是不可能的吗?

3 个答案:

答案 0 :(得分:2)

我同意Maz在这里,你仍然可以从查询处理和创建对象中受益,也不需要为此修补jquery

但是,如果您不介意修补jquery,可以添加这些行

        // The readystate 2
        } else if ( !requestDone && xhr && xhr.readyState === 2 && isTimeout !== 'timeout' && s.state2) {
            s.state2.call( s.context, data, status, xhr );
        // The readystate 3
        } else if ( !requestDone && xhr && xhr.readyState === 3 && isTimeout !== 'timeout' && s.state3) {
            s.state3.call( s.context, data, status, xhr );

在这一行之前:(jQuery v 1.4.4)或者只是在源中搜索readyState === 4

        // The transfer is complete and the data is available, or the request timed out
        } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {

现在你可以再次使用$ .ajax并为state2和state3设置一个处理程序,如下所示:

$.ajax({
    url: 'http://www.stackoverflow.com',
    cache: false,
    success:function(){console.log('success');},
    error: function (){console.log('error');},
    complete: function (){console.log('complete');},
    state2: function (context,data,status,xhr) {console.log('state2');},
    state3: function (context,data,status,xhr) {console.log('state3');}
});

它并不像其他处理程序那样完全表现,例如,returnngin false不会做任何事情 但你仍然可以处理xhr对象并以此方式中止

看看我是否可以在今天晚些时候将其提交到源代码中,谁知道他们可能会接受它

答案 1 :(得分:1)

如果您需要大量的自定义,您可以获取XMLHttpRequest对象并自行控制它。

var x=new $.ajaxSettings.xhr();
x.onreadystatechange=function(){ ... }
...

答案 2 :(得分:-1)

你可以通过这样做来做到这一点:

$.ajax({
type: "POST",
url: "Test.ashx",
data: { "command": "test" },
contentType: "application/x-www-form-urlencoded; charset=utf-8",
dataType: "json",
beforeSend: function (request, settings) {
    $(request).bind("readystatechange", function (e) { alert("changed " + e.target.readyState); });
}});