Как перехватить все запросы AJAX, сделанные различными библиотеками JS
Я создаю веб-приложение с различными библиотеками JS (AngularJS, OpenLayers,...) и нужен способ перехватить все ответы AJAX, чтобы иметь возможность, если зарегистрированный сеанс пользователя истек (ответ возвращается с 401 Unauthorized
status), чтобы перенаправить его на страницу входа в систему.
Я знаю, AngularJS предлагает interceptors
для управления такими сценариями, но не смог найти способ добиться такой инъекции в запросы OpenLayers. Поэтому я выбрал ванильный JS подход.
здесь я нашел этот кусок кода...
(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);
...который я адаптировал и выглядит так, как и ожидалось (только протестировал его на последнем Google Chrome).
поскольку он изменяет прототип XMLHTTPRequest, мне интересно, насколько это может быть опасно или может вызвать серьезные проблемы с производительностью. И, кстати, есть ли какая-то действительная альтернатива?
Update: как перехватить запросы, прежде чем они получат отправлен
предыдущий трюк работает нормально. Но что, если в том же сценарии вы хотите ввести некоторые заголовки до отправки запроса? Сделайте следующее:
(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);
4 ответов
этот тип функции закрепляя совершенно безопасен и сделан регулярно на других методах по другим причинам.
и единственное влияние на производительность-это действительно только один дополнительный вызов функции для каждого .open()
плюс любой код, который вы выполняете сами, который, вероятно, нематериален, когда задействован сетевой вызов.
в IE это не поймает код, который пытается использовать ActiveXObject
метод управления выполнением Ajax. Хорошо написанный код выглядит первым для XMLHttpRequest
объект и использует это, если доступно, и это было доступно с IE 7. Но может быть какой-то код, который использует ActiveXObject
метод, если он доступен, который был бы истинным через гораздо более поздние версии IE.
в современных браузерах есть и другие способы выдачи вызовов Ajax, такие как fetch()
интерфейс поэтому, если вы хотите подключить все вызовы Ajax, вам нужно подключить больше, чем просто XMLHttpRequest
.
как любезно указал редактор Firefox AMO Rob W
,
следующий код изменяет поведение XMLHttpRequest. По умолчанию, если третий параметр ("async") не указан, по умолчанию используется истинный. Когда он указан и не определен, он эквивалентен " false", который превращает запрос в синхронный HTTP-запрос. В этом случае UI для блокировки во время обработки запроса и некоторые функции API XMLHttpRequest отключены тоже.
...
чтобы исправить это, замените open.призывать.(...) с открытым.применить(это, аргументы);
и вот ссылка:
Ajax-hook является открытым исходным кодом lib для подключения глобального объекта 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])
}
})
Это не поймает XMLHttpRequests для некоторых версий IE (9 и ниже). В зависимости от библиотеки они могут сначала искать собственный элемент управления ActiveX IE.
и, конечно, все ставки отключены, если вы используете нестрогий DOCTYPE под IE, но я уверен, что вы это знали.
ссылки: CanIuse