18

I have a factory from a separate module that I would like to inject into a provider for my module, but I keep getting unknown provider errors. What am I doing wrong?

What I would like to inject:

var angularSocketIO = angular.module('socketioModule', []);
angularSocketIO.factory('socketio', [
    '$rootScope', 
    'addr', 
    function($rootScope, addr) {
        var socket = io.connect(addr,{
            'sync disconnect on unload': true
        });
                ...
        return socket;
    }
]);

Where I am trying to inject it:

angular.module('myApp.services', ['socketioModule'])
    .provider('greeter', ['socketio', function(socket) {
        var salutation = 'Hello';
        this.setSalutation = function(s) {
            salutation = s;
        }

        function Greeter(a) {
            this.salutation = salutation;
            socket._emit('hello')

            this.greet = function() {
                return salutation + ' ' + a;
            }
        }

        this.$get = function(version) {
            return new Greeter(version);
        };
    }]);

That results in

Error: [$injector:modulerr] Failed to instantiate module myApp due to:
[$injector:modulerr] Failed to instantiate module myApp.services due to: 
[$injector:unpr] Unknown provider: socketio

2 Answers 2

22

I think is because all the providers are instantiated before the factories and so a provider has to depend only on other providers.

As a way around that, I am using the injector method of angular.module to create the module. A plunker that should do what you were trying to accomplish: http://plnkr.co/edit/g1M7BIKJkjSx55gAnuD2

Notice that I changed also the factory method. The factory method is now returning an object with a connect method.

var angularSocketIO = angular.module('socketioModule', ['ng']);
angularSocketIO.factory('socketio', [
    '$rootScope',
    function($rootScope) {
      return {
        connect: function(addr) {
          var socket = io.connect(addr, {
            'sync disconnect on unload': true
          });

          return socket;
        }
      };
    }]);


  angular.module('myApp.services', ['socketioModule'])
  .provider('greeter', [
    function() {
      var injector = angular.injector(['socketioModule']);
      var socketio = injector.get('socketio');

      var salutation = 'Hello';
      this.setSalutation = function(s) {
        salutation = s;
      }

      function Greeter(a) {
        this.salutation = salutation;
        socket._emit('hello');

        this.greet = function() {
          return salutation + ' ' + a;
        };
      }

      this.$get = function(version) {
        return new Greeter(version);
      };
    }
  ]);


  var myApp = angular.module('myApp', ["myApp.services"]);
Sign up to request clarification or add additional context in comments.

6 Comments

That did the trick, but only when I included the ng in the socket module. What is that portion doing? Also, if my factory were switched to a provider do you think that would fix it as well? I was thinking I might switch that to get the config ability. Thanks for the help!
I had the same issue, and ended up using the injector...is there a best practice here? In my case, I was injecting factory that wrapped lodash into a provider called "config" (wanted to use lodash's _extend b/c angular's 'extend' sucks). Didn't seem to make sense stylistically to make that factory a provider just so i could inject it into another provider. But curious as to what the "best" way to do it would have been...
Hmm, what would be the best practice though? I did the same thing and I'm feeling a bit dirty to have done that :))
"...a provider has to depend only on other providers.". I needed a provider to depend on another provider - in order to get this to work, the app must declare the depended provider first (basically, order of declaration matters in this case).
@herringtown Since lodash is available before angular bootstrap phase, just use .constant('lodash', _)
|
10

I think you can add dependencies via $get method in provider:

angular.module('myApp.services', ['socketioModule'])
  .provider('greeter', [
    function() {
        ...
        this.$get = ['socketio', function(socket, version) {
            function Greeter(a) {
                  this.salutation = salutation;
                  socket._emit('hello')

                  this.greet = function() {
                      return salutation + ' ' + a;
                  }
             }
             return new Greeter(version);
      }];
   }  
]);

Comments

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.