Services vs. Factories in Angular
EDIT 2016. Note that this post, which is a repost of a post from 2015, is about Angular 1. I don’t do frontend anymore so no guarantees that this post is relevant to Angular 2 ;).
Moxe Health
One of my Hack Reactor classmates and I recently built a high blood pressure treatment calculator for Moxe Health, an exciting Rock Health company that is building a database integration system and API that will allow any developer to access the electronic medical records of any hospital in Moxe’s network. I’m excited to talk about Moxe and the project in another post. We built the front-end of the app in Angular, a powerful front-end framework with data binding and other awesome features. One thing that was confusing was when to use services vs. factories. Stack Overflow has a good thread on the difference between the two, but it leaves out some analogies that I think are useful to developers still cementing their Javascript knowledge.
In this post, you’re going to learn the difference between the two.
TLDR — factories and services have pretty much the same functionality in terms of their ability to instantiate and enscapsulate methods and properties, much like functional instantiation and pseudoclassical instantiation patterns have similar abilities. There is no preference in the Angular community for using one or the other. Factory and service recipes are just syntactic sugar on top of the provider recipe. So the question you should be asking yourself is usually not “should I be using factories or services?” it’s “should I be using functional instantation or pseudoclassical instantiation?”
Other than that high-level understanding, the most significant difference is that as a result of the difference in their instantiation patterns, factories can return primitives and functions, but services can’t.
Primitives, functions, and objects, oh my!
Check out this JSFiddle. Credit to Epokk for providing most of the code. I made a couple of modifications that again, really help developers new to Angular to drill down on the difference here. If you’re new to JSFiddle, it’s a tool that allows you to easily test interactions between your javascript, html, and css files. So you can play around with the code, and it won’t overwrite the original code in the link.
Both the service and the factory in this example have the same functionality of returning the string “Hello World!”. The difference is how they do it.
The service instantiates an object and assigns the function that returns “Hello World!” to the “sayHello” property of that object:
this.sayHello = function() { return "Hello, World!" };The method is then invoked in the controller: helloWorldFromService.sayHello().
The factory returns a function that returns “Hello World!”:
return function() { return "Hello, World!" };The function is then invoked in the controller: helloWorldFromFactory(). Note how the factory’s reference points to the returned function, rather than the property of an object whose value is a function, as in the service example. A service could never do this, because a service must instantiate an empty object whose reference within the service function body is ‘this’. Services always return objects.
Here’s the part of factories that can be confusing. The factory can also return an object that has a method ‘sayHello’, much like the service:
return { sayHello: function() { return "Hello, World!" } };Which you would invoke in the controller exactly as you would invoke the service’s sayHello function: helloWorldFromFactory.sayHello().
The latter factory format is useful when you want to have multiple methods in a factory:
return { sayHello: function() { return "Hello, World!" }, sayGoodbye: function() { return "Goodbye, World!" } };Again, the key here is not getting caught up in the fact that you’re coding in Angular, and remembering that the differences between services and factories are for the most part the same as the differences between pseudoclassical instantiation and functional instantiation.
Source code for the curious
Here’s the Angular source code, demonstrating that services & factories are layered on top of the more general providers feature:
//provider function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) { throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); } return providerCache[name + providerSuffix] = provider_; } //factory function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } //service function service(name, constructor) { return factory(name, ['$injector', function($injector) { return $injector.instantiate(constructor); }]); }Both service and factory create singletons. Basic functional vs. pseudoclassical inheritance patterns here. The factory returns whatever the factoryFn returns.
The service returns an instance of a pseudo-class. The pseudo-class’s constructor is passed to Angular’s service builder service(). The fact that the constructor is passed to the service builder service (return $injector.instantiate(constructor)) can be confusing, but just think of it as return new constructor().
Happy coding!
Originally published at www.shanemkeller.com, April 2014.