An Introduction to Angular Services


Warning: Illegal string offset 'filter' in /var/sites/t/theproactiveprogrammer.com/public_html/wp-includes/taxonomy.php on line 1409

Service Client on the Cogwheels.

This post is the third in a series looking at some of the fundamental concepts of Angular. Here is the first part, and here is the second.

What is a service?

Most programmers are familiar with the concept of services in software architecture, particularly since the proliferation of Domain-Driven Design. Services carry out tasks for clients. They describe what they can do, and based on this you, the client, choose whether or not to take advantage of the service on offer. You are not really concerned with how they do it, just with the end result. If I take my suit to the dry cleaners, I don’t really care about the type of equipment they use or how they go about the task. All I am concerned with are inputs and outputs. If I give you my suit (input), and you give it back to me dry cleaned (output), then I am satisfied with your service.

Services in software are quite similar, and Angular is no exception. We create services to carry out tasks for clients, where the client in Angular is typically either a controller or another service. The dry cleaners might use other services to help them meet the requirements of their clients, and software services can equally use other services to help them serve their clients. Another key feature of services in software architecture is that they are reusable. As long as the inputs are valid, the outputs are guaranteed, whoever the client is.

In Angular, there are three things in particular which you should know about services:

  • Angular services are wired to controllers and other services using dependency injection.
  • Angular services are singletons (unlike controllers, which can have multiple instances).
  • There are five ‘recipes’ for creating services in Angular. These recipes are called Provider, Value, Factory, Constant and (confusingly) Service*.

How do services make use of dependency injection?

We have seen in previous articles how to create an Angular controller. For example:

Plunker

In this example we call the controller function with two parameters: a name for the controller and a constructor function. In order to inject a service into this controller, we need to modify our code as follows:

Plunker

We are doing three things differently here.

Firstly, we need to define and register our service so that we can use it. Remember how there are 5 recipes for creating services? Notice how here we are using the factory recipe, which according to the Angular documentation is the recipe which we should typically use. Each recipe has a corresponding function name defined on the module API. The way we register our service here is very similar to the way we register a directive: we provide a name and a factory function.

Secondly, we pass the name of our service as a parameter into our call to app.controller() – this specifies the service as a required dependency for the controller. Notice how we are now using an array as the second parameter to the controller function, where its first item is the dependency and its second is our constructor function. If we have multiple dependencies, we list them all before specifying the constructor function.

Finally, we add a parameter to our constructor function for each dependency. This allows us to access the service from inside the controller.

And services are singletons?

Services in Angular are singletons, which means of course that only one exists, even though the service may be used by many controller instances and services across your application. A single instance of each service can serve multiple clients.

This approach obviously has advantages in terms of memory utilisation, we just need to be aware of it if we are storing state in a service object which is shared between multiple clients:

Plunker

What are the 5 recipes for creating services?

In the examples above, we have used the factory recipe for creating services. This is clear as we have called the factory function on our module to declare the service. The factory recipe will be appropriate for most services, however as mentioned above there are in fact 5 recipes for creating services in Angular. The remaining four will be discussed in next week’s post.

* Angular acknowledge their mistake in naming one of their service recipes ‘service’. From the official website: “Note: Yes, we have called one of our service recipes ‘Service’. We regret this and know that we’ll be somehow punished for our misdeed. It’s like we named one of our offspring ‘Child’. Boy, that would mess with the teachers”.

Share Button