jQuery Ajax, перезаписать обработчик onreadystatechange

Я недавно дурачился с некоторыми методами опроса ajax. Тем не менее, кажется, что я не могу перезаписать onreadystatechange обработчик из XMLHttpRequest объект в FireFox (3.6.7).

При отслеживании проблемы, почему 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 не позволяет перезаписывать обработчик на этом этапе.

Заключение?

Невозможно создать custom readystatechange handler с помощью jQuery /Firefox?

3 ответа

Решение

Я согласен с 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.stackru.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');}
});

он не ведет себя точно так же, как другие обработчики, например, returngin false не будет ничего делать, но вы все равно можете обработать объект xhr и прервать его таким образом

Посмотрим, смогу ли я представить это, чтобы включить в источник позже в этот день, кто знает, что они могут принять это

Если вам нужен большой уровень настройки, вы можете просто получить объект XMLHttpRequest и управлять им самостоятельно.

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

Вы можете сделать это, сделав что-то вроде этого:

$.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); });
}});
Другие вопросы по тегам