首页 > JavaScript监听全部ajax请求的事件

JavaScript监听全部ajax请求的事件

最近在做一个项目,其中需要监听页面中不可控代码调用 ajax 请求的事件,比如说监听调用 XHR 后的 onreadystatechangeonloadonloadstart 等事件。

嗯,主要是用原生的 JavaScript 实现。查了挺多资料的,大概的做法是:

1、Pub/Sub,也就是 https://github.com/cowboy/jquery-tiny-pubsub 这个 jQuery 插件。但是因为调用 ajax 请求的代码不可控,无法添加 publish,或者说我不会添加?

2、jQuerybindtrigger,同上,代码不可控

3、如果是用 jQuery 实现的,可以直接监听其 ajaxCompete 等事件,然而调用 ajax 请求的并不是 jQuery$.ajax,故此招没用

4、如果 ajax 的回调涉及到 DOM 操作,还可以使用 MutationObserver,但是最多只能知道 ajax 成功并且更新了 DOM,不能监听到 onreadystatechange 等事件

5、直接重写 XHR,配合 CustomEvent 实现

那些已被弃用或降级的方法不作考虑。


针对第五点,查找到了国外相关资料,其做法见如下代码

var open = window.XMLHttpRequest.prototype.open,
        send = window.XMLHttpRequest.prototype.send,
        ReadyStateChange;

    function openReplacement(method, url, async, user, password) {
        open.apply(this, arguments);
    }

    function sendReplacement(data) {
        var ajaxReadyStateChange,
            ajaxLoad;
        console.warn('Sending HTTP request data : ', data);

        // onreadystatechange replacement
        if (this.onreadystatechange) {
            ReadyStateChange = this.onreadystatechange;
        }
        this.onreadystatechange = function () {
            console.warn('HTTP request ready state changed : ' + this.readyState);
            ajaxReadyStateChange = new CustomEvent('ajaxReadyStateChange', { detail: this });
            window.dispatchEvent(ajaxReadyStateChange);

            if(ReadyStateChange) {
                ReadyStateChange.apply(this, arguments);
            }

            // onload
            if (this.readyState === 4) {
                ajaxLoad = new CustomEvent('ajaxLoad', { detail: this });
                dispatchEvent(ajaxLoad);
            }
        };

        send.apply(this, arguments);
    }

    window.XMLHttpRequest.prototype.open = openReplacement;
    window.XMLHttpRequest.prototype.send = sendReplacement;

但是问题在于,onreadystatechange 事件在调用 send 方法时才被绑定,所以无法监听到 readyState01 状态。而且如果不可控代码中绑定如 onreadystatechange 事件时在调用 send 方法之后,就会使得重写的事件失效。直接 this.addEventListener 没试过。


所以我想直接添加类似于下面这样的代码,当然下面的肯定没用:

window.XMLHttpRequest.onload = function () {
    alert('')
}

做到所有 ajax 在触发其事件前,先执行我重写的函数,不知能否实现?

若调用 ajax 的是 $.ajax,除了上面我提到的,还有什么实现方法?

望赐教,谢谢

【热门文章】
【热门文章】