Should I use
factory? What’s the difference?
Angular makes things a little confusing by giving you the option of registering objects as services or factories. Their behavior is very similar, and some people will say that either one is fine. That’s somewhat true, but I find it easier to follow the advice of John Papa’s style guide and just stick with factories.
But you came here to learn the difference between the two, so let’s look at that.
Both of them…
Are Singletons – No matter which you choose, they are both singletons. Angular will create a single instance the first time it sees a dependency on your service/factory, and use that single instance forevermore.
Can be used to model an object with behavior – They can both have methods, internal state variables, and so on. Though the way you write that code will differ, and we’ll see how that works below.
A factory is a plain old function that returns a value. The return value is what gets injected into things that depend on the factory. A typical factory pattern in Angular is to return an object with functions as properties, like this:
Depending on your personal style, you might find it more readable to organize the code this way instead:
It’s a little easier to tell at-a-glance what the factory exposes as its public API this way.
If it seems weird to you that there are functions defined after the
return, perhaps you haven’t yet
As I mentioned above, the injected value for a factory dependency is the factory’s return value, and it doesn’t have to be an object. It could be a function (Angular’s built-in
$filter does this). That would look something like this:
A service is a constructor function, and Angular will instantiate it by calling
new yourService(). This means a couple things.
- Behavior (functions) and instance variables will be properties of
- You don’t need to return a value. When Angular calls
new yourService(), it’ll receive the
thisobject with all the properties you put on it.
An example service might look like this:
Notice: no return value, and methods are properties on
When Angular injects this
UserManager service into a controller that depends on it, that controller will get a
UserManager that it can call functions on, e.g.
Be careful with
Since the constructed service is an object, the methods inside it can refer to
this when they’re called:
You might be tempted to call
ScoreKeeper.setScore in a promise chain, for instance if you initialized the score by grabbing it from the server:
$http.get('/score').then(ScoreKeeper.setScore). The trouble with this is that
ScoreKeeper.setScore will be called with
this bound to
null and you’ll get errors. The better way would be
$http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper)), but it doesn’t read as nicely.
Whether you choose to use
this in your service methods or not, be careful how you call them.
Returning a value from a service
This means that you can basically copy-paste the
factory example from above, replace
service, and it’ll work:
So when Angular constructs your service with
new UserManager(), it’ll get that
api object instead of the
This is the behavior for any complex values (objects, functions) but not for primitive types. Try it out! Open your browser console and type these in:
Then try executing each one as a regular function, and as a constructor function with
new, like so:
The best way to gain an intuitive understanding of this behavior is to play around with it.
Just Use Factories*
For the most part, just stick with using factories for everything. Their behavior is easier to understand. There’s no choice to make about whether to return a value or not, and furthermore, no bugs to be introduced if you do the wrong thing.
I still refer to them as “services” when I’m talking about injecting them as dependencies, though.
* You noticed that asterisk there?
Ok, well there are a few cases where a service is actually a better choice. As Mike mentioned in the comments, Angular’s built-in
$resource service is a great example of something that makes more sense as a service, because it actually needs to be instantiated. It models data, in addition to having prototype methods for behavior.
So if you’re writing something that seems more like a proper “object oriented” object, consider doing it as a service instead of a factory.
Learning React can be a struggle — so many libraries and tools!
My advice? Ignore all of them :)
For a step-by-step approach, check out my Pure React workshop.
Learn to think in React
- 90+ screencast lessons
- Full transcripts and closed captions
- All the code from the lessons
- Developer interviews
Dave Ceddia’s Pure React is a work of enormous clarity and depth. Hats off. I'm a React trainer in London and would thoroughly recommend this to all front end devs wanting to upskill or consolidate.