Hitesh Kumar Hitesh Kumar - 5 months ago 18
AngularJS Question

Why I am able to access angular service without injecting module?

I am playing with angular services and finding that I am able to use an angular service without even injecting it's

module
. I have created 3 modules i.e.
moduleA, moduleB, app
.
moduleA
&
moduleB
are independent of each other but
app
module depends on
moduleA
and
moduleB
. This is how I am creating modules.

angular.module('moduleA',[]);
angular.module('moduleB',[]);
angular.module('app',['moduleA', 'moduleB']);


In
moduleA
I have a service
ServiceA
and in
moduleB
I have a service
ServiceB
. This how I am defining services:

moduleA <-- ServiceA:

(function() {
var app = angular.module('moduleA', []);
app.service('ServiceA', function() {
'use strict';
this.greet = function() {
alert('Greetings From Service A');
};
});
}());


moduleB <-- ServiceB: I have injected
serviceA
in
serviceB
.

(function() {
'use strict';
var app = angular.module('moduleB', []);
app.service('ServiceB', function(ServiceA) {
// I have not injected moduleA in moduleB but still
// Don't know why I am able to access ServiceA
// in ServiceB. Ideally I should not be able to access
// anything which is defined in moudleA unlesss and until
// I do not inject moduleA in moudleB.
console.log(ServiceA);
this.greet = function() {
ServiceA.greet();
};
});
}());


And in the end
app Module:

(function() {
'use strict';
var app = angular.module('app', ['moduleA', 'moduleB']);
app.controller('MainController', ['$scope', 'ServiceA', 'ServiceB', function($scope, ServiceA, ServiceB) {
$scope.greet = function() {
ServiceB.greet();
};
}])
}());


Now the concern is that I am not injecting
moduleA
in
moduleB
but still I am able to access
ServiceA
of
moduleA
in
ServiceB
of
moduleB
.
I don't know why this is happening. What I understand from module is that they are similar to
package
or
namespace
of Java or Dot Net. Whatever we create in a module lies in that particular module. To get services or special objects defined in that module I have to inject the module. But don't know why I am able to access it without even injecting it. Here's the fiddle to play.

Answer

When a module is loaded, its services become available for injection. Once service provider is defined on current $injector, it holds no information which module it belongs to.

The code above is workable, but it designates a bad habit, because it will render unworkable if moduleA is not loaded. As a rule of thumb, modules should load modules which they depend on. It is acceptable to load a module in several dependent modules, it will be loaded only once.

The things become more complicated with provider injector in config block (there are two separate $injectors for service providers and service instances).

For this loading order

angular.module('app',['moduleA', 'moduleB']); 

this will work as expected, because ServiceA service provider was already defined when config block runs:

angular.module('moduleB', []).config(function (ServiceAProvider) { ... });

And for this loading order

angular.module('app',['moduleB', 'moduleA']); 

injector error will be thrown, because config block runs before app.service('ServiceA', ...) defines ServiceAProvider service provider. app.service method may run earlier than config, but service definitions are queued and don't take effect immediately.