Подтвердить что ты не робот

Мне нужно два экземпляра услуги AngularJS $http или что?

Я хочу добавить ответный перехватчик в мою службу $http для обработки ошибок. Логика перехватчика включает сообщения об ошибках отправки на сервер с использованием $http в случае необходимости, НО я не хочу отправлять сообщения об ошибках на сервер об ошибках сообщений, я имею в виду, я хочу отключить мой перехватчик при отправке сообщения об ошибке на сервер.

Моя идея заключалась в создании сервиса с именем "remote_log" и вставка внутри него всего кода, необходимого для отправки ошибки на сервер. Конечно, эта служба будет использовать службу $http и иметь ее в своем списке зависимостей.

Затем добавьте в качестве зависимости перехватчика к службе "remote_log" и используйте "remote_log" внутри перехватчика, когда вам нужно отправить ошибки на сервер. Проблемы заключаются в следующем:

Перехватчики должны быть определены с помощью $httpProvider, когда служба $http по-прежнему не создается/не доступна, поэтому внутри кода перехватчика не может быть зависимость от службы $http, так как происходит ошибка "Круговая зависимость".

Я думаю, что мой единственный вариант - создать отдельный экземпляр службы $http внутри моего "удаленного_лога", экземпляр, который не использует конфигурацию $httpProvider, которую я установил при создании перехватчика. Мой вопрос: как я могу это сделать? Любые другие идеи?

4b9b3361

Ответ 1

1. Проблема круговой зависимости.

Итак, почему появляется ошибка? Вот краткий обзор процесса:

  • $http запрашивается.
  • $httpProvider просят его создать.
  • Во время строительства вы регистрируете перехватчик, который запрашивает еще $http-службу.
  • Вы получаете ошибку "Круговая зависимость".


Первое решение.

Создайте свою зависимость, используя angular.injector(). Обратите внимание, что вы создадите еще одну службу $http, независимо от вашего приложения.

$httpProvider.interceptors.push(function($q) {
    $injector = angular.injector();
    return {
        response: function(response) {
            $injector.invoke(function($http) {
                // This is the exterior $http service!
                // This interceptor will not affect it.
            });
        }
    };
});


Второе решение (лучше).

Внесите $инжектор в ваш перехватчик и используйте его для получения зависимостей после инициализации $http, прямо в то время, когда вы в них нуждаетесь. Эти зависимости являются зарегистрированными службами вашего приложения и не будут созданы заново!

$httpProvider.interceptors.push(function($q, $injector) {
    return {
        response: function(response) {
            $injector.invoke(function($http, someService) {
                // $http is already constructed at the time and you may
                // use it, just as any other service registered in your
                // app module and modules on which app depends on.
            });
        }
    };
});


2. Проблема предотвращения перехвата.

Если вы используете второе решение, есть две проблемы:

  • Если вы используете службу $http внутри своего перехватчика, вы можете закончиться бесконечными перехватами: вы отправляете запрос, перехватчик улавливает его, отправляет другого, ловит другого, отправить еще раз и т.д.
  • Иногда вам нужно просто запретить перехват запроса.

Параметр 'config' службы $http - это всего лишь объект. Вы можете создать соглашение, предоставить настраиваемые параметры и распознать их в своих перехватчиках.

Например, добавьте свойство "nointercept" в конфигурацию и попробуйте дублировать каждый запрос пользователя. Это глупое приложение, но полезный пример для понимания поведения:

$httpProvider.interceptors.push(function($q, $injector) {
    return {
        response: function(response) {
            if (response.config.nointercept) {
                return $q.when(response); // let it pass
            } else {
                var defer = $q.defer();
                $injector.invoke(function($http) {
                    // This modification prevents interception:
                    response.config.nointercept = true;
                    // Reuse modified config and send the same request again:
                    $http(response.config)
                        .then(function(resp) { defer.resolve(resp); },
                              function(resp) { defer.reject(resp); });
                });
                return defer.promise;
            }
        }
    };
});

После тестирования свойства в перехватчике вы можете предотвратить перехват в контроллерах и службах:

app.controller('myController', function($http) {
    // The second parameter is actually 'config', see API docs.
    // This query will not be duplicated by the interceptor.
    $http.get('/foo/bar', {nointercept: true})
        .success(function(data) {
            // ...
        });

});

Ответ 2

Я использовал то, что описано в ответе, но я использовал синтаксис с factory, потому что с анонимной функцией это не сработало, я действительно не знаю, почему:

(function(angular){
    angular.module('app', [])
    .config([
        '$httpProvider',
        function($httpProvider) {
                $httpProvider.interceptors.push('Interceptor');
        } 
    ])
    .factory('Interceptor', [
        '$injector',
        InterceptorFactory
    ]);

    function InterceptorFactory($injector){

        return {
            request: function(config) {             
                var ServiceWithHttp = $injector.get('ServiceWithHttp');
                // Use ServiceWithHttp
                return config;
            }
        };
    }

}(window.angular));