Как перехватить все запросы AJAX, сделанные разными JS-библиотеками

Я создаю веб-приложение с различными JS-библиотеками (AngularJS, OpenLayers,...) и нуждаюсь в возможности перехватить все ответы AJAX, чтобы иметь возможность, в случае, если истекший сеанс сеанса пользователя (ответ возвращается с 401 Unauthorized status), чтобы перенаправить его на страницу входа.

Я знаю, что AngularJS предлагает interceptors управлять такими сценариями, но не смог найти способ добиться такой инъекции в запросы OpenLayers. Поэтому я выбрал подход Vanilla 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, мне интересно, насколько это может быть опасно, или может вызвать серьезные проблемы с производительностью. И, между прочим, будет какая-то действительная альтернатива?

Обновление: как перехватывать запросы до их отправки

Предыдущий трюк работает нормально. Но что, если в том же сценарии вы хотите ввести некоторые заголовки перед отправкой запроса? Выполните следующие действия:

(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 это не поймает никакого кода, который пытается использовать метод управления ActiveXObject для выполнения Ajax. Хорошо написанный код выглядит сначала для объекта XMLHttpRequest и использует это, если он доступен, и доступен с IE 7. Но может быть какой-то код, который использует метод ActiveXObject, если он доступен, который был бы правдой через гораздо более поздние версии IE.


В современных браузерах существуют другие способы выпуска вызовов Ajax, таких как fetch() интерфейс, поэтому, если вы хотите подключить все Ajax вы должны перехватить больше, чем просто XMLHttpRequest.

Ответ 2

Это не приведет к сбою XMLHttpRequests для некоторых версий IE (9 и ниже). В зависимости от библиотеки они могут сначала искать собственный элемент управления ActiveX IE.

И, конечно, все ставки отключены, если вы используете нестандартный DOCTYPE в IE, но я уверен, что вы это знали.

Ссылка: CanIuse

Ответ 3

Как любезно указана Firefox AMO Editor Rob W,

Следующий код изменяет поведение XMLHttpRequest. По умолчанию, если третий ( "асинхронный" ) параметр не указан, по умолчанию используется правда. Когда он указан и undefined, он эквивалентен "false", который превращает запрос в синхронный HTTP-запрос. Это вызывает UI для блокировки во время обработки запроса, а также некоторые функции API XMLHttpRequest также отключен.

...

Чтобы исправить это, замените open.call(....) на open.apply(это, аргументы);

И вот ссылка:

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