I need two instances of AngularJS $http service or what? I need two instances of AngularJS $http service or what? angularjs angularjs

I need two instances of AngularJS $http service or what?


1. Circular dependency problem.

So, why does the error appear? Here is a quick overview of the process:

  1. $http service is requested.
  2. $httpProvider is asked to construct it.
  3. During construction you register interceptor, that requests $http service not existing yet.
  4. You get "Circular dependency" error.


First solution.

Create your dependency using angular.injector(). Notice, that you will create another $http service, independent from your app.

$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.            });        }    };});


Second solution (better).

Inject $injector in your interceptor and use it to retrieve dependencies after $http initialization, right at the time you need them. These dependencies are registered services of your app and will not be created anew!

$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. Interception prevention problem.

If you use the second solution, there are actually two problems:

  1. If you utilize $http service inside yourinterceptor, you may end up with infinite interceptions: you sendrequest, interceptor catches it, sends another, catches another,send again, and so on.
  2. Sometimes you want just prevent request from being intercepted.

The 'config' parameter of $http service is just an object. You may create a convention, providing custom parameters and recognizing them in your interceptors.

For example, let's add "nointercept" property to config and try duplicate every user request. This is a silly application, but useful example to understand the behavior:

$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;            }        }    };});

Having the testing for property in interceptor, you may prevent the interception in controllers and services:

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) {            // ...        });});


I used what is described in the answer but I used the syntax with a factory because with the anonymous function it didn't work, I don't really know why:

(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));