小编典典

重新创建jQuery的ajaxStart和ajaxComplete功能

ajax

我正在尝试在没有jQuery的情况下重现jQuery的函数ajaxCompleteajaxStart,以便可以在没有库依赖项的任何环境中使用它们(这是一个特殊的用例)。这些功能允许在任何ajax请求之前和之后调用事件侦听器。在我的示例中,我将它们称为preAjaxListener和postAjaxListener。

我正在尝试通过连接到XMLHttpRequest对象并覆盖/装饰openand 来实现它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请求。我希望能够挂接到页面上任何库(或使用香草js)发出的任何ajax请求。

到目前为止,仅该preAjaxListener功能有效。我似乎无法弄清楚为什么,但似乎onreadystatechange从未有人称呼过。任何指导将不胜感激。

工作演示:http :
//jsfiddle.net/_nderscore/QTQ5s/


阅读 259

收藏
2020-07-26

共1个答案

小编典典

使用.onreadystatechange不起作用,因为我正在使用jQuery进行测试,并且jQuery的ajax方法可以操纵并删除该onreadystatechange属性。

但是,为loadendIE 添加事件侦听器的方法在所有地方都可以正常工作。对于IE,我改为设置时间间隔-不是最佳解决方案,但它可以满足我的需要。
我只打算将此脚本用于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);
2020-07-26