angular.service vs angular.factory
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...
Such as writing a service function to expose a public API:
function myServiceFunction() { this.awesomeApi = function(optional) { // calculate some stuff return awesomeListOfValues; }}---------------------------------------------------------------------------------// Injected in your controller$scope.awesome = myInjectedService.awesomeApi();
Or using a factory function to expose a public API:
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();
Or using a factory function to return a constructor:
function myFactoryFunction() { return function() { var a = 2; this.a2 = function() { return a*2; }; };}---------------------------------------------------------------------------------// Injected in your controllervar myShinyNewObject = new myInjectedFactory();$scope.four = myShinyNewObject.a2();
Which one to use?...
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.)
One more thing, they are all Singletons...
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.)
Simply put ..
const user = { firstName: 'john'};// Factoryconst addLastNameFactory = (user, lastName) => ({ ...user, lastName,});console.log(addLastNameFactory(user, 'doe'));// Serviceconst addLastNameService = (user, lastName) => { user.lastName = lastName; // BAD! Mutation return user;};console.log(addLastNameService(user, 'doe'));
Here are the primary differences:
Services
Syntax: module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided with the instance of a function passed to module.service
.
Usage: Could be useful for sharing utility functions that are useful to invoke by simply appending ( )
to the injected function reference. Could also be run with injectedArg.call( this )
or similar.
Factories
Syntax: module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided with the value that is returned by invoking the function reference passed to module.factory
.
Usage: Could be useful for returning a 'class' function that can then be new'ed to create instances.
Here is example using services and factory. Read more about AngularJS Service vs Factory.
You can also check the AngularJS documentation and similar question on stackoverflow confused about service vs factory.