AngularJS: Injecting service into a HTTP interceptor (Circular dependency)

Recently, I’m getting circular dependency error while I’m injecting my service to HTTP interceptor. Code works well if I’m remove my service dependency from HTTP interceptor.

Find my interceptor code below where I’m injecting my ‘waitingDialog‘ service which have ‘$uibModal’ (angular ui-modal) dependency.

(function () {
    'use strict';

    angular
        .module('app')
        .factory('waitingDialog', ['$uibModal', function($uibModal){
            var service = {};
            var modalInstance;
            service.show = show;
            service.hide = hide;

            function show(msg, size) {
                msg = msg || "Loading";
                size = size || 'lg';

                modalInstance = $uibModal.open({
                    template: msg,
                    size: size
                });
            }

            function hide() {
                modalInstance.close();
            }


            return service;
        }])
        .factory('clientHttpErrorInterceptor', ['$q', 'waitingDialog', function ($q, waitingDialog) {

            var apiRoot = '';
            var activeRequests = 0;

            var requestStart = function(){
                if(activeRequests == 0){
                    waitingDialog.show(); //Show loader
                }
                activeRequests++;
            };
            var requestEnd = function(){
                activeRequests--;
                if (activeRequests == 0) {
                    waitingDialog.hide(); // Hide loader
                }
            };
            return {
                request: function (config) {
                    if(config.url.indexOf("/api/") > -1) {
                        requestStart();
                    }
                    return config || $q.when(config);
                },

                requestError: function (rejection) {
                    if (rejection.config.url.indexOf("/api/") > -1) {
                        requestEnd();
                    }
                    return $q.reject(rejection);
                },

                response: function (response) {
                    if(response.config.url.indexOf("/api/") > -1) {
                        requestEnd();
                    }

                    return response || $q.when(response);
                },

                responseError: function (rejection) {
                    if(rejection.config.url.indexOf("/api/") > -1) {
                        requestEnd();
                    }

                    return rejection || $q.when(rejection);
                }
            };

        }]);
})();

This is what I’m getting error in my console:

Circular dependency found: $http <- $templateRequest <- $uibModal <- waitingDialog <- clientHttpErrorInterceptor <- $http

After some googling I got to know that if you register a interceptor on $httpProvider you can not inject a service which depends itself on $http as you get a circular dependency loop due to $http being instantiated when $httpProvider is accessed – Github-issue# 2367.

Here in my case ‘waitingDialog‘ service have dependency ‘$uibModal‘. While ‘$uibModal‘ have dependency of ‘$templateRequest‘ -> ‘$http‘. So this is the reason I’m getting circular dependency error.

Now let see how do I can fix this issue:

We need to inject ‘$injector‘ and use it inside interceptor to inject my ‘waitingDialog‘ service manually. Instead of ‘waitingDialog.show() ‘ I need to use ‘$injector.get(‘waitingDialog’).show();‘. Have a look my interceptor code below:

(function () {
    'use strict';

    angular
        .module('app')
        .factory('waitingDialog', ['$uibModal', function($uibModal){
            var service = {};
            var modalInstance;
            service.show = show;
            service.hide = hide;

            function show(msg, size) {
                msg = msg || "Loading";
                size = size || 'lg';

                modalInstance = $uibModal.open({
                    template: msg,
                    size: size
                });
            }

            function hide() {
                modalInstance.close();
            }


            return service;
        }])
        .factory('clientHttpErrorInterceptor', ['$q', '$injector', function ($q, $injector) {

            var apiRoot = '';
            var activeRequests = 0;

            var requestStart = function(){
                if(activeRequests == 0){
                    $injector.get('waitingDialog').show(); //Show loader
                }
                activeRequests++;
            };
            var requestEnd = function(){
                activeRequests--;
                if (activeRequests == 0) {
                    $injector.get('waitingDialog').hide(); // Hide loader
                }
            };
            return {
                request: function (config) {
                    if(config.url.indexOf("/api/") > -1) {
                        requestStart();
                    }
                    return config || $q.when(config);
                },

                requestError: function (rejection) {
                    if (rejection.config.url.indexOf("/api/") > -1) {
                        requestEnd();
                    }
                    return $q.reject(rejection);
                },

                response: function (response) {
                    if(response.config.url.indexOf("/api/") > -1) {
                        requestEnd();
                    }

                    return response || $q.when(response);
                },

                responseError: function (rejection) {
                    if(rejection.config.url.indexOf("/api/") > -1) {
                        requestEnd();
                    }

                    return rejection || $q.when(rejection);
                }
            };

        }]);
})();

That’s it 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s