Angular comes with different types of services. Each one with its own use cases.
Something important that you have to keep in mind is that the services are always singleton, it doesn’t matter which type you use. This is the desired behavior.
NOTE: A singleton is a design pattern that restricts the instantiation of a class to just one object. Every place where we inject our service, will use the same instance.
Let’s start with my own opinion about services.
1 2 3 4
A constant is a useful service often used to provide default configurations in directives. So if you are creating a directive and you want to be able to pass options to it but also at the same time to give it some default configurations, a
constant service is a good way to go.
As a constant, the values we put in there can’t be changed in any way. The
constant service expects a primitive or an object.
1 2 3 4
value service is like the
constant service but the first one can be changed. It is used in directives too, to hold configuration. A
value service is like the small brother of a
factory, it only holds values and we cannot compute those values in the service.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Factory is the most common used service. It is also the easiest to understand.
factory is a service which can return any datatype. There is no opinion of how you need to create it, you only need to return something. When working with objects, I like to work with the Revealing module pattern, but you can use the approach you want.
As I said before, all types are singleton, so if we modify
foo.variable in one place, the other places will have that change too.
1 2 3 4 5 6 7
service service works much the same as the
factory one. The difference is that
service receives a constructor, so when you use it for the first time, it will do a
new Foo(); to instantiate the object. Keep in mind that it will return the same object if you use this service again in other places.
In fact, it is the same thing as doing this:
1 2 3 4 5 6 7 8 9 10 11 12
Foobar is a class and we instantiate it in our
factory the first time we use it and then we return it. Like the service, the
Foobar class will be instantiated only once and the next time we use the
factory it will return the same instance again.
If we already have the class and we want to use it in our
service we can do that like the following:
Provider is the big brother of
factory. In fact our
factory from the last example is something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
provider expects a
$get function that will be what we inject into other parts of our application. So when we inject
foo into a controller, what we inject is the
Why should we use this form when a
factory is much simple? Because we can configure a
provider in the config function. So we can do something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Here we moved the
thisIsPrivate outside our
$get function and then we created a
setPrivate function to be able to change
thisIsPrivate in a config function. Why do we need to do this? Won’t it be easier to just add the setter in the
factory? This has a different purpose.
We want to inject a certain object but we want to provide a way to configure it for our needs. For example: a service that wraps a resource using jsonp and we want to be able to config which URL we want to use or, we are consuming a 3rd party service like
restangular that allows us to configure it to our purposes.
Notice that we have to put
nameProvider instead of just
name in our config function. To consume it, we just need to use
Seeing this we realize that we already configured some services in our applications, like
$locationProvider, to configure our routes and html5mode respectively.
Bonus 1: Decorator
So you decided that the
foo service I sent to you lacks a
greet function and you want it. Will you modify the
factory? No! You can decorate it:
1 2 3 4 5 6 7 8 9
$provide is what Angular uses to create all of our services internally. We can use it by hand if we want to or just use the functions provided in our modules (we need to use
$provide for decorating).
$provide has a function,
decorator, that lets us decorate our services. It receives the name of the service that we are decorating and the callback receives a
$delegate which is our original service instance.
Here we can do what we want to decorate our service. In our case, we added a
greet function to our original service. Then we return the new modified service.
Now when we consume it, it will have the new
greet function as you will see in the
The ability to decorate services comes in handy when we are consuming 3rd party services and we want to decorate it without having to copy it in our project and then doing there the modifications.
constant service cannot be decorated.
Bonus 2: Creating new instances
Our services are singleton but we can create a singleton factory that creates new instances. Before you dive deeper, keep in mind that having singleton services is the way to go and we don’t want to change that. Said that, in the rare cases you need to generate new instances, you can do that like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
Here we create a
Person object which receives some json to initialize the object. Then we created a function in our prototype (functions in the prototype are for the instances of the
Person) and a function directly in
Person (which is like a class function).
So we have a class function that will create a new
Person object based on the id that we provide (well, it will in real code) and every instance is able to update itself. Now we just need to create a service that will use it.
Every time we call
personService.getById we are creating a new
Person object, so you can use this service in different controllers and even when the factory in a singleton, it generates new objects.
Kudos to Josh David Miller for his example.
Bonus 3: Coffeescript
Coffeescript can be handy with services since they provide a prettier way to create classes. Let’s see an example of the
Bonus 2 using Coffeescript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
It is prettier now in my humble opinion.
Services are one of the coolest features of Angular. We have a lot of ways to create them, we just need to pick the correct one for our use cases and implement it.
If you found any issue or you think that this can be improved, please leave an issue or pull request at Github. In any case, a comment will be appreciated :).