Як перехопити всі запити AJAX, зроблені різними бібліотеками JS


110

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

Я знаю, що 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, мені цікаво, наскільки це може призвести до небезпеки або якщо це може спричинити серйозні проблеми з продуктивністю. І до речі, чи була б якась вагома альтернатива?

Оновлення: як перехопити запити, перш ніж їх надсилати

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

(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
Мені здається абсолютно безпечним.
Вармар

Єдиний вплив на ефективність полягає в тому, що він виконуватиме додаткову функцію під час кожної відповіді AJAX, але це те, що ви хочете зробити.
Бармар

я шукав щось подібне. велике спасибі
Срібна Місяця

Відповіді:


36

Цей тип функціональних підключень є абсолютно безпечним і проводиться регулярно іншими методами з інших причин.

І єдиний вплив на продуктивність - це лише один додатковий виклик функції для кожного .open()плюс будь-який код, який ви виконуєте самостійно, що, мабуть, несуттєво, якщо задіяний мережевий дзвінок.


У IE це не вловить жодного коду, який намагається використовувати ActiveXObjectметод керування Ajax. Добре написаний код спочатку виглядає для XMLHttpRequestоб'єкта і використовує те, якщо він є, і він доступний з IE 7. Але може бути якийсь код, який використовує ActiveXObjectметод, якщо він доступний, що було б істинно через набагато пізніші версії IE.


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


1
Привіт @ jfriend00 - як би ви підключили всі запити на отримання api - stackoverflow.com/questions/44728723/… ?
colemerrick

1
@bagofcole - Ви, мабуть, можете мавпочку виправити fetch()функцію, щоб перехопити всі виклики до неї - хоча я цього ніколи не пробував. Схоже, що цей модуль робить це.
jfriend00

Зриває YouTube при спробі підключення comment_service_ajaxзапитів.
Лірой

3

Це не сприймає XMLHttpRequests для деяких версій IE (9 і нижче) . Залежно від бібліотеки, вони можуть спочатку шукати власне управління ActiveX IE.

І, звичайно, усі ставки знімаються, якщо ви використовуєте не суворий ДОКТИП під IE, але я впевнений, що ви це знали.

Довідка: CanIuse


2

Як ласкаво вказав редактор AMO Firefox Rob W,

Наступний код змінює поведінку XMLHttpRequest. За замовчуванням, якщо третій ("асинхронний") параметр не вказаний, він за замовчуванням відповідає істині. Коли він вказаний та невизначений, він еквівалентний "false", який перетворює запит у синхронний HTTP-запит. Це призводить до блокування інтерфейсу користувача під час обробки запиту, а деякі функції API XMLHttpRequest також відключені.

...

Щоб виправити це, замініть open.call (....) на open.apply (це, аргументи);

А ось довідкове посилання:

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


(де "Наступний код" посилається на фрагмент запитання)
Rob W
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.