Have you ever found yourself asking: should I use a value? a factory? a service? a provider?! Ask yourself 3 questions:
Then reduce which type of service you need to use:
Notice that if you answer yes to the third question you don’t need to ask yourself the other questions - optimizing the algorithm :)
Angular modules have a config phase, that runs before the app is bootstrapped. During that phase you can only inject constants or providers. You cannot inject a service or a value:
angular.module('app', [])
.config(function(Constant, Provider) {
// ...
})
.controller(function(Service, Value, ...) {
})
;
Constants and values can't inject dependencies. Thus, they are simpler to define:
angular.module('app', [])
.constant('PI', Math.PI)
.value('Temperature', 27.5)
In most cases, there's no real justification for using a value over a constant. The main advantage I found, is that you can override it in tests, in order to mock it.
To understand why you never need to use a factory, you need to know how the injector instantiates our services.
For a service, it's something like this:
service = new Service(dependency1, dependency2, ...)
For a factory, it's something like this:
factory = Factory(dependency1, dependency2, ...)
In Javascript a constructor function can ignore the fact that it was called with new
operator, and act as a regular function, returning whatever it likes. For example:
function Service() {
return { value: 3 };
}
var service = new Service();
// service.value === 3;
function AnotherService() {
this.value = 3;
}
var anotherService = new AnotherService();
// anotherService.value === 3;
However, if it hasn't been called with new, you can't use it as a constructor, but you have to return a value. For example:
function Factory() {
this.value = 3;
}
factory = Factory();
// factory === undefined;
Thus, you can replace all your factories with services, and everything will work the same way, but not the other way around.
*disclaimer: There's only thing you can't return from a constructor function invoked with new is a primitive value (string, integer, etc.). So the only case it will make sense to use a factory is for defining primitive values that require dependencies.
Hope you enjoyed the guide!