I have seen both angular.factory() and angular.service() used to declare services; however, I cannot find angular.service
anywhere in official documentation.
angular.service('myService', myServiceFunction);
angular.factory('myFactory', myFactoryFunction);
I had trouble wrapping my head around this concept until I put it to myself this way:
Service: the function that you write will be new-ed:
myInjectedService <---- new myServiceFunction()
Factory: the function (constructor) that you write will be invoked:
myInjectedFactory <--- myFactoryFunction()
What you do with that is up to you, but there are some useful patterns...
function myServiceFunction() {
this.awesomeApi = function(optional) {
// calculate some stuff
return awesomeListOfValues;
}
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.awesome = myInjectedService.awesomeApi();
function myFactoryFunction() {
var aPrivateVariable = "yay";
function hello() {
return "hello mars " + aPrivateVariable;
}
// expose a public API
return {
hello: hello
};
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.hello = myInjectedFactory.hello();
function myFactoryFunction() {
return function() {
var a = 2;
this.a2 = function() {
return a*2;
};
};
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();
You can accomplish the same thing with both. However, in some cases the factory gives you a little bit more flexibility to create an injectable with a simpler syntax. That's because while myInjectedService must always be an object, myInjectedFactory can be an object, a function reference, or any value at all. For example, if you wrote a service to create a constructor (as in the last example above), it would have to be instantiated like so:
var myShinyNewObject = new myInjectedService.myFunction()
which is arguably less desirable than this:
var myShinyNewObject = new myInjectedFactory();
(But you should be wary about using this type of pattern in the first place because new-ing objects in your controllers creates hard-to-track dependencies that are difficult to mock for testing. Better to have a service manage a collection of objects for you than use new()
wily-nilly.)
Also keep in mind that in both cases, angular is helping you manage a singleton. Regardless of where or how many times you inject your service or function, you will get the same reference to the same object or function. (With the exception of when a factory simply returns a value like a number or string. In that case, you will always get the same value, but not a reference.)