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

时间:2014-08-15 23:44:59

标签: javascript ajax interceptor

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

我知道AngularJS提供401 Unauthorized来管理这些场景,但是无法找到实现这种注入OpenLayers请求的方法。所以我选择了一种普通的JS方法。

Here我找到了这段代码......

interceptors

...我对其进行了调整,看起来像预期的那样(仅在最后一次谷歌浏览器上测试过)。

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

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

上一个技巧可行。但是如果在同一个场景中你想在发送请求之前注入一些标题呢?执行以下操作:

(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);

5 个答案:

答案 0 :(得分:31)

这种类型的功能挂钩非常安全,并且出于其他原因定期在其他方法上完成。

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


在IE中,这不会捕获任何试图使用ActiveXObject控制方法来执行Ajax的代码。编写良好的代码首先查找XMLHttpRequest对象并使用该代码(如果可用)并且自IE 7以来一直可用。但是,如果可用,可能会有一些代码使用ActiveXObject方法在IE的更新版本中都是如此。


在现代浏览器中,还有其他方式可以发出Ajax调用,例如fetch() interface,所以如果要挂钩所有Ajax调用,则必须挂钩而不仅仅是XMLHttpRequest

答案 1 :(得分:3)

对于某些版本的IE (9及以下),它不会捕获XMLHttpRequests。根据库,他们可能首先寻找IE的专有ActiveX控件。

当然,如果你在IE下使用非严格的DOCTYPE,所有的赌注都会被取消,但我确定你知道这一点。

参考:CanIuse

答案 2 :(得分:3)

Ajax-hook是一个用于挂钩全局XMLHttpRequest对象的开源库,并更改了默认的Ajax请求和响应。 github:https://github.com/wendux/Ajax-hook,例如:

hookAjax({

  //hook callbacks
  onreadystatechange:function(xhr){
   console.log("onreadystatechange called: %O",xhr)
  },

  onload:function(xhr){
   console.log("onload called: %O",xhr)
  },

  //hook function
  open:function(arg,xhr){
   console.log("open called: method:%s,url:%s,async:%s",arg[0],arg[1],arg[2])
  }

})

答案 3 :(得分:2)

正如Firefox AMO编辑Rob W所指出的,

  

以下代码更改了XMLHttpRequest的行为。默认情况下,   如果未指定第三个(" async")参数,则默认为   真正。当指定和未定义时,它等同于" false",   它在同步HTTP请求中转换请求。这导致了   在处理请求时阻止的UI,以及一些功能   XMLHttpRequest API也被禁用。

...

  

要解决此问题,请将open.call(....)替换为open.apply(this,arguments);

以下是参考链接:

https://xhr.spec.whatwg.org/#the-open()-method

答案 4 :(得分:0)

试试这个

let oldXHROpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {

console.log({method});

// Show loader

 this.addEventListener('load', function() {
  console.log('load: ' + this.responseText);
  // Hide loader
 });
           
  return oldXHROpen.apply(this, arguments);
}