Воспроизведение jQuery ajaxStart и функции ajaxComplete

Я пытаюсь воспроизвести функции jQuery ajaxComplete и ajaxStart без jQuery, чтобы их можно было использовать в любой среде без каких-либо зависимостей библиотеки (это специальный прецедент). Эти функции позволяют вызывать прослушиватель событий до и после любого запроса ajax. В моем примере я называю их preAjaxListener и postAjaxListener.

Я пытаюсь выполнить его, подключившись к объекту XMLHttpRequest и переписывая/украшая open и send. Да, я знаю, что это грязно.

XMLHttpRequest.prototype.open = (function(orig){
    return function(a,b,c){
        this._HREF = b; // store target url
        return orig.apply(this, arguments); // call original 'open' function
    };
})(XMLHttpRequest.prototype.open);

XMLHttpRequest.prototype.send = (function(orig){
    return function(){
        var xhr = this;
        _core._fireAjaxEvents('pre', xhr._HREF); // preAjaxListener fires

        var rsc = xhr.onreadystatechange || function(){}; // store the original onreadystatechange if it exists
        xhr.onreadystatechange = function(){ // overwrite with custom function
            try {
                if (xhr.readyState == 4){
                    _core._fireAjaxEvents('post', xhr._HREF); // postAjaxListneer should fire
                    this.onreadystatechange = rsc;
                } 
            } catch (e){ }
            return rsc.apply(this, arguments); // call original readystatechange function
        };

        return orig.apply(this, arguments); // call original 'send' function
    };
})(XMLHttpRequest.prototype.send);

Я не хочу писать функции-обертки для создания ajax-запросов. Я хочу иметь возможность подключиться к любому запросу ajax, сделанному любой библиотекой (или с ванильным js) на странице.

Пока работает только функция preAjaxListener. Я не могу понять, почему, но кажется, что onreadystatechange никогда не называется. Любое руководство будет с большой благодарностью.

Рабочая демонстрация: http://jsfiddle.net/_nderscore/QTQ5s/

Ответ 1

Использование .onreadystatechange не работало, потому что я тестировал с помощью jQuery и jQuery. ajax-методы управляют и удаляют свойство onreadystatechange.

Однако добавление прослушивателя событий для loadend отлично работает везде, кроме IE. Для IE я настраивал интервал вместо этого - не оптимальное решение, но оно работает для моих нужд. Я использовал этот script для работы с IE8 + и современными браузерами.

XMLHttpRequest.prototype.send = (function(orig){
    return function(){
        _core._fireAjaxEvents('pre', this._HREF);

        if (!/MSIE/.test(navigator.userAgent)){
            this.addEventListener("loadend", function(){
                _core._fireAjaxEvents('post', this._HREF);
            }, false);
        } else {
            var xhr = this,
            waiter = setInterval(function(){
                if(xhr.readyState && xhr.readyState == 4){
                    _core._fireAjaxEvents('post', xhr._HREF);
                    clearInterval(waiter);
                }
            }, 50);
        }

        return orig.apply(this, arguments);
    };
})(XMLHttpRequest.prototype.send);