我正在使用不同的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);
答案 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);
以下是参考链接:
答案 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);
}