AngularJS provides a few different ways in which we can to create and register services (and constants and values), depending on our preference and style of programming. In the previous section, we used the factory function to define our services. You should use module.factory() to define your services if:
- You follow a functional style of programming
- You prefer to return functions and objects
Let’s see how the service we defined in the previous example changes if we use the service() function:
In this example, we can use the exact same controllers and HTML from before. We can use this app.js with the index.html from the previous example. We only display the part that is changed, which is the service definition:
- The first thing of note is that we now use service instead of factory for defining our AngularJS service.
- Our service defines the public API by defining methods (add, list) on its instance(using the this keyword).
- Private state for the service is still defined as local variables inside the function definition.
- AngularJS will perform new ItemService() (with possible dependencies injected in) and then return that instance to all functions that depend on ItemService.
The third and final way of defining services is using the provider function. This is not a very common approach, but can be useful when we need to set up some configuration for our service before our application loads. We will deal with application-level configuration later, but with the provider, we can have functions that can be called to set up how our service works based on the language, environment, or other things that are applicable to our service. Let’s see how that might look:
We introduced two new concepts in this example. The rest of the controllers and HTML remain the same as before, so use the same index.html from the factory example:
- ItemService now takes in the list of default items as an argument to the constructor.
- ItemService is declared using a provider. We define a function in the provider called disableDefaultItems. This can be called in the configuration phase of an AngularJS application. That is, this can be called before the AngularJS app has loaded and the service has been initialized.
- Note that the provider does not use the same notation as factory and service. It doesn’t take an array as the second argument because providers cannot have dependencies on other services.
- The provider also declares a $get function on its instance, which is what gets called when the service needs to be initialized. At this point, it can use the state that has been set up in the configuration to instantiate the service as needed.
Let’s take a look at the config function that we have defined:
- The config function executes before the AngularJS app executes. So we can be assured that this executes before our controllers, services, and other functions.
- The config function follows the same Dependency Injection pattern, but gets providers injected in. In this case, we ask for the ItemServiceProvider.
- At this point, we can now call functions and set values that the provider exposes. We are able to the call the disableDefaultItems function that we defined in the provider.
- The config function could also set up URL endpoints, locale information, routing configuration for our application, and so on: things that need to be executed and initialized before our application starts.
- We can try changing the value of shouldHaveDefaults to true (this would come from the server or URL, or some other way usually) to see the effect it has on our application.