如何拦截不同 JS 库发出的所有 AJAX 请求

2022-08-30 05:05:17

我正在构建一个具有不同JS库(AngularJS,OpenLayers,...)的Web应用程序,并且需要一种方法来拦截所有AJAX响应,以便在记录的用户会话过期的情况下(响应返回状态)能够将他重定向到登录页面。401 Unauthorized

我知道AngularJS提供了管理此类场景的功能,但无法找到一种方法来实现对OpenLayers请求的这种注入。所以我选择了一种普通的JS方法。interceptors

这里我发现这段代码...

(function(open) {

    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {

        this.addEventListener("readystatechange", function() {
            console.log(this.readyState); // this one I changed
        }, false);

        open.call(this, method, url, async, user, pass);
    };

})(XMLHttpRequest.prototype.open);

...我适应了它,看起来它的行为符合预期(仅在最后一个谷歌浏览器上进行了测试)。

当它修改XMLHTTPRequest的原型时,我想知道这可能导致多大的危险,或者它是否会产生严重的性能问题。顺便说一句,会有什么有效的替代方案吗?

更新:如何在发送请求之前拦截请求

前面的技巧工作正常。但是,如果在同一场景中,您希望在发送请求之前注入一些标头,该怎么办?请执行下列操作:

(function(send) {

    XMLHttpRequest.prototype.send = function(data) {

        // in this case I'm injecting an access token (eg. accessToken) in the request headers before it gets sent
        if(accessToken) this.setRequestHeader('x-access-token', accessToken);

        send.call(this, data);
    };

})(XMLHttpRequest.prototype.send);

答案 1

这种类型的函数挂钩是完全安全的,并且由于其他原因在其他方法上定期完成。

而且,唯一的性能影响是每个函数调用实际上只有一个额外的函数调用,以及您自己执行的任何代码,这在涉及网络调用时可能无关紧要。.open()


在IE中,这不会捕获任何尝试使用执行Ajax的控制方法的代码。编写良好的代码首先查找对象,如果可用并且自IE 7以来一直可用,则使用它。但是,如果该方法可用,则可能有一些代码可以使用该方法,这在更高版本的IE中是正确的。ActiveXObjectXMLHttpRequestActiveXObject


在现代浏览器中,还有其他方法可以发出Ajax调用,例如fetch()接口,因此,如果要挂接所有Ajax调用,则必须挂接的不仅仅是。XMLHttpRequest


答案 2

这不会捕获某些版本的IE(9及更低版本)的XMLHttpRequests。根据库的不同,他们可能会首先查找IE专有的ActiveX控件。

而且,当然,如果您在IE下使用非严格的DOCTYPE,则所有赌注都会关闭,但我相信您知道这一点。

参考资料:康宇斯