0

I am getting the following exception 'Unknown provider: authSvc' which is originating in my config.js file which I will post below. I understand this error means my authSvc module has not been registered and is unavailable, but the service is created before I try injecting it. Can someone please help me? I am lost on this one...so thought I'd turn to SO. Thanks.

index.html

<!doctype html>
<html class="no-js" lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="apple-touch-icon" href="apple-touch-icon.png">
        <!-- Place favicon.ico in the root directory -->

        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
        <link rel="stylesheet" href="css/normalize.css">
        <link rel="stylesheet" href="css/main.css">
        <!-- <script src="js/vendor/modernizr-2.8.3.min.js"></script> -->
        <script data-main="js/main" src="js/vendor/require.js"></script>     
    </head>
    <body>
        <!--[if lt IE 8]>
            <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <nav class="navbar navbar-inverse navbar-fixed-top" ng-controller="navCtrl">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Brand</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
                <li><button class="btn btn-default navbar-btn" ng-click="login()">Login</button></li>
                <li><button class="btn btn-info navbar-btn" ng-click="register()">Register</button></li>
            </ul>
        </div><!--/.navbar-collapse -->
      </div>
    </nav>
        <div ng-view></div>
    </body>
</html>

main.js

require.config({

    paths: {
        'angular': 'vendor/angular',
        'domReady': 'vendor/domready',
        'angularRoute': 'vendor/angular-route',
        'angularLocalStorage': 'vendor/angular-local-storage',
        'bootstrapCss': 'vendor/bootstrap-css'
    },

    shim: {
        'angular': {
            exports: 'angular'
        },
        'angularRoute': {
            deps: ['angular']
        },
        'angularLocalStorage': {
            deps: ['angular']
        }
    },

    deps: ['./bootstrap']
});

bootstrap.js

require([
    'angular', 
    'app',
    'services/authSvc',
    'controllers/navCtrl',
    'controllers/landingPageCtrl',
    'controllers/homeCtrl',
    'controllers/loginCtrl',
    'config',
    'routes'
    ], function (angular) {
    'use strict';

    angular.element(document).ready(function () {
        angular.bootstrap(document, ['myApp']);
    });

});

app.js

define([
    'angular',
     'angularRoute',
     'angularLocalStorage'
 ], function(angular, angularRoute, angularLocalStorage) {

'use strict';

var app = angular.module('myApp', ['ngRoute', 'LocalStorageModule']);

return app;

});

authSvc.js

define(['app'], function(app) {

    app.service('authSvc', function($http, localStorageService) {

        this.setToken = function(token) {
            return localStorageService.set('token', token);
        }

        this.getToken = function() {
            return localStorageService.get('token');
        }

        this.login = function(username, password) {
            return $http.post('/api/login', {username: username, password: password});
        }

    });

    console.log('authSvc registered');

});

config.js

define(['app'], function(app) {
    'use strict';

    app.config(function($httpProvider, authSvc) {
        $httpProvider.interceptors.push(function($q) {
          return {
           'request': function(config) {
               // same as above
               //config.headers.token = authSvc.getToken();
               return config;
            },

            'response': function(response) {
               // same as above
               return response;
            }
          };
        });
    });

    console.log('config registered');

});
2
  • If anyone can help out, my project is completely stalled until I can sort this out. I have checked the network panel of my console and things are being loaded in the order they are in inside bootstrap.js, meaning the service is being created before .config() is called with the service injected. Makes no sense whatsoever that it is throwing Unknown Provider Commented Jan 24, 2016 at 16:27
  • Update: Been tinkering around, noticed that authSvc works fine when injected into a controller, for example navCtrl, just throws Unknown Provider when injected into .config(). Is this a bug? Commented Jan 24, 2016 at 16:35

1 Answer 1

1

You cannot inject services in config blocks. Only providers.

app
    .factory('yourInterceptor', yourInterceptor)
    .config(configureInterceptor);

function configureInterceptor($httpProvider) {
    $httpProvider.interceptors.push('yourInterceptor');
}

function yourInterceptor(authSvc) {
    return {
        'request': function (config) {
            // same as above
            //config.headers.token = authSvc.getToken();
            return config;
        },

        'response': function (response) {
            // same as above
            return response;
        }
    };
}

EDIT:

Pass injector to your interceptor and get the service instance using the injector

function yourInterceptor($injector) {
    return {
        'request': function (config) {
            var authService = $injector.get('authSvc');


            //config.headers.token = authSvc.getToken();
            return config;
        },

        'response': function (response) {
            // same as above
            return response;
        }
    };
}
Sign up to request clarification or add additional context in comments.

6 Comments

So if I have a service which gets a auth token from local storage, how can I inject that service into a http interceptor inside app.config()? Thanks.
I guess the only solution is to not use app.service('authSvc', ...)?
I'm going to try the way you are doing it in your edit in a moment, if it works I'll mark it as the answer.
I have done it the way you suggested and now a new error happens: Circular dependency found: $http <- authSvc <- myInterceptor <- $http <- $templateRequest <- $compile When I remove $http from authSvc, this goes away. But I need $http in authSvc to make API calls.
No worries, glad i could help ;)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.