6

I have a simple question about the dependency injection in Angular. I create custom services in order to use them within each other. Unfortunately I receive errors the way I was trying it. This is my Code:

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

myApp.service('$service1', ['$rootScope', function($rootScope) {
    this.test = function() {
        console.log('service1');
    };
}]);

myApp.provider('$service2', ['$service1', function($service1) {

    var service = 'service2';

    this.registerService = function(mytext) {
        service = mytext;
    }; 

    this.$get = function() {
        var that = {};
        that.test = function() {
            console.log(service);  
        };
        return that;
    };
}]);

myApp.config(['$service2Provider', function($service2Provider) {
    $service2Provider.registerService('changed service2');
}]);


myApp.controller('AppCtrl', ['$rootScope', '$service1', '$service2',
    function($rootScope, $service1, $service2) {
        $service1.test();
        $service2.test();  
}]);

Error: [$injector:modulerr] Failed to instantiate module app due to: [$injector:unpr] Unknown provider: $service1 http://errors.angularjs.org/1.2.0-rc.2/$injector/unpr?p0=%24service1

If you remove the dependency of $servic1 in $service2 it will work, but why?

user2911527
  • 63
  • 1
  • 4

2 Answers2

2

The code is mostly right, except you have to inject service dependencies in $get, not in the provider constructor function, like this:

myApp.provider('$service2', function() {

    var service = 'service2';

    this.registerService = function(mytext) {
        service = mytext;
    }; 

    this.$get = ['$service1', function($service1) {
        var that = {};
        that.test = function() {
            console.log(service);  
        };
        return that;
    }];
});
Buu
  • 49,745
  • 5
  • 67
  • 85
  • 1
    But why do it this complicated when using a factory achieves the same and is more easy and less code? – Juliane Holzt Oct 23 '13 at 22:35
  • Because `myApp.config(['$service2Provider', function($service2Provider) { $service2Provider.registerService('changed service2'); }]);` makes it possible to extend the behaviour of the provider. I am using this approach for an common oauth interface. – user2911527 Oct 28 '13 at 13:48
1

It appears that provider can not inject such a dependency. If you rewrite $service2 using a factory, it works:

myApp.factory('$service2', ['$service1', function($service1) {
  var that = {};
  that.test = function() {
    $service1.test();
    console.log('service2');  
  };
  return that;
}]);

See this plunker: http://plnkr.co/edit/JXViJq?p=preview

Also I believe that service names starting with a $ a reserved for AngularJS and its extensions. Use names without the $ at the beginning for services defined by your application.

Juliane Holzt
  • 2,135
  • 15
  • 14
  • From my point of view `$` is not reserved by AngularJS. It just helps me to remember that this is a service not a "normal" function or object. I choose `provider` because I want to extend the functionality of `$service2` is something like this possible with type `factory` too? – user2911527 Oct 23 '13 at 15:16
  • ``factory``, ``service``, ``provider`` and ``value`` are basically the same thing, they just differ in how they are instantiated. ``provider`` is the lowlevel feature which is in the end use by all these variants. So you shall be able to achieve the same functionality regardless of which variant you use (except for ``value``). See also this answer: http://stackoverflow.com/a/15666049/2572897 – Juliane Holzt Oct 23 '13 at 15:20
  • I was thinking that way. But there is no example of a service used in a provider. And If you try my example, you will see, that it is not possible to use it that way, without getting errors. – user2911527 Oct 23 '13 at 15:34
  • But why do you want to bother with calling ``provider`` directly if it does not work? As the other answer shows, the ``factory`` function does use ``provider`` in the end as well. So there shall be nothing (or nothing important in your case) which you can do in a provider, which you can't do when using the factory. – Juliane Holzt Oct 23 '13 at 15:38
  • Excuse me? I have explained that by using a ``factory`` it does work and have even provided you with a Plunker which shows it working. – Juliane Holzt Oct 23 '13 at 22:33
  • 1
    @kju `factory`, `service`, `provider` and `value` are NOT the same thing. They have similar uses, but in different phases of your application or module, and are critical to consider when structuring the architecture of your build. AngularJS could do a better job of highlighting this, instead of relegating this chart in the bottom of the docs for providers: http://docs.angularjs.org/guide/providers – Brian Vanderbusch Feb 09 '14 at 18:27
  • 1
    I said that they are "basically" the same thing and this is still true. They only differ in how the object in question is instantiated. Don't believe me? See yourself in the AngularJS source code and notice that - as i wrote - all end up using "provider". I have not said, that they are readily interchangeable, but still, in most cases you can achieve your goal with any of them. – Juliane Holzt Apr 09 '14 at 12:19