AngularJS Services Dissected

AngularJS services

AngularJS services are functions or objects that can hold behavior or state throughout application. They are used to implement shared behavior/reusable logic which can be used by other components in your AngularJS application. AngularJS services are singletons, means each service is instantiated only once, so each part of our application gets access to the same instance of the AngularJS service. AngularJS services are lazily instantiated, means Angular only instantiates a service when an application component who depends on it [another service, controller or directive e.g.], gets loaded.

Do note that AngularJS services are different than AngularJS controllers. Controllers are created and destroyed several times while navigating to different views, but services are instantiated only once and then reused everywhere in application.

Common use of Services : Communicating with Server, Repeated behavior, Reusable business logic, application-level stores, shared state, etc.

AngularJS services & Dependency Management

The whole AngularJS service concept is driven by AngularJS Dependency Injection system. Any service can be injected into another service, controller or directive, by just declaring it as a dependency, and AngularJS will do the rest.

AngularJS Built-in services

$log, $window, $location, $http are few examples of built-in services. A built-in AngularJS service name starts with $. For complete list, check out the AngularJS documentation.

The ‘Service’ word in AngularJS is bit overloaded. To avoid confusion, we should talk in terms of Provider. A Provider means someone who provides a value-added service to accomplish something. In AngularJs, The value, factory, service, constant, and provider methods are all Providers. They provide instructions to AngularJS about how to instantiate the different type of services. What differentiate them from each other is there intention & role in application. All the providers are instantiated only once, means they are all singletons. We will see all of them in detail.

An AngularJS service can be implemented as a factory, service, or provider. Choosing specially between factory and provider depends on your coding style and preference.

1. Factory

A Factory is created using module.factory function. It is useful if you follow a functional style of programming and you prefer to return functions and objects.

<html ng-app="myApp">
  <head>  
    <title>Factory Demo</title>  
  </head>
  <body ng-controller="AppController as ctrl">
   
    <label>Name :</label><input type="text" ng-model="ctrl.name" placeholder="Enter your name"/><br/><br/>  
 
    <span ng-bind="ctrl.message"></span> <br/><br/>  
 
    <button ng-click="ctrl.hello()"> Hello Message </button>  
    <button ng-click="ctrl.bye()"> Bye Message </button>  
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js">
    </script>  
    <script>
        angular.module('myApp',[])
        .factory('GreetingService', [function() {
            return {
                    sayHello : function(name) {
                          return "Hello " + name;
                     },
                    sayBye : function(name) {
                          return "Bye " + name;
                     }
            }
        }])
        .controller('AppController', ['GreetingService', function(GreetingService) {
             var self = this;
             self.name='';
             self.message='';
             self.hello = function() {
                  self.message = GreetingService.sayHello(self.name);
             };
         
             self.bye = function(name) {
                  self.message = GreetingService.sayBye(self.name);
             };
         
        }]);  
        </script>
  </body>
</html>

Live Demo

In this case, service definition function of factory returns an object [with two methods that can be invoked], which becomes the public API for our service.

2. Service

A Service is created using module.service function. It is useful if you follow a Class/OO style of programming, where we define classes and types instead of functions and objects. With service, the function definition is actually a class/type, and AngularJS calls new on it to create an instance of it. But remember. only one instance will be created, as we know that AngularJS services are singletons.

<html ng-app="myApp">
  <head>  
    <title>Factory Demo</title> 
    <style>body{font-family:"Arial";background-color:#E2E2DC}</style> 
  </head>
  <body ng-controller="AppController as ctrl">
   
    <label>Name :</label><input type="text" ng-model="ctrl.name" placeholder="Enter your name"/><br/><br/>  
 
    <span ng-bind="ctrl.message"></span> <br/><br/>  
 
    <button ng-click="ctrl.hello()"> Hello Message </button>  
    <button ng-click="ctrl.bye()"> Bye Message </button>  
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js">
    </script>  
    <script>
        angular.module('myApp',[])
          .service('GreetingService', [function() {
                this.sayHello = function(name) {
                    return "Hello " + name;
                };
                     
                this.sayBye = function(name) {
                    return "Bye " + name;
                };
        }])
        .controller('AppController', ['GreetingService', function(GreetingService) {
             var self = this;
             self.name='';
             self.message='';
             self.hello = function() {
                  self.message = GreetingService.sayHello(self.name);
             };
         
             self.bye = function(name) {
                  self.message = GreetingService.sayBye(self.name);
             };
         
        }]);  
        </script>
  </body>
</html>

Live Demo

Take special note that our service definition function is now a JavaScript class function. It doesn’t return anything. AngularJS will perform new GreetingService() (with possible dependencies injected in) , cache it, and then return that instance to all components that depends on GreetingService. Note that since new was used to instantiate the service, the keyword this is valid and refers to the instance.

Interestingly, nothing changes in Controller’s code and in HTML compare to previous Factory example. Only difference between these two examples are use of Factory vs Service or i can say ‘return from function’ vs ‘new service’.

3. Provider

Creating an AngularJS Service using provider is not a very common approach, but comes handy when you want to provide a configuration for your service before it can be used. A provider is used to create a configurable service object. In this approach you usually provide the service configuration using module.config function. Provider includes a $get function which gets executed in run phase. It is the return value from the $get function [the service which you configured based on your requirement] that will be cached and injected when the service is requested.

<html ng-app="myApp">
  <head>  
    <title>Service Demo</title> 
    <style>body{font-family:"Arial";background-color:#E2E2DC}</style> 
  </head>
  <body ng-controller="AppController as ctrl">
   
    <label>Name :</label><input type="text" ng-model="ctrl.name" placeholder="Enter your name"/><br/><br/>  
 
    <span ng-bind="ctrl.message"></span> <br/><br/>  
 
    <button ng-click="ctrl.hello()"> Hello Message </button>  
    <button ng-click="ctrl.bye()"> Bye Message </button>  
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js">
    </script>  
    <script>
    function MessagingService(queueType) {
        
        this.getQueueType = function() {
            return queueType;
        };
        
        this.sayHello = function(name) {
            return "Hello " + name +", Sent using "+ queueType;
        };
                     
        this.sayBye = function(name) {
            return "Bye " + name +", Sent using "+ queueType;
        };
      
    } 
    
    angular.module('myApp',[])
        .provider('MessagingService', function() {
              var env='';
              this.setEnvironment = function(environment) {
                  env = environment;
              };
              // This function gets any injected dependencies, not the provider above.
              this.$get = [function() {
                  var queueType = '';
                  if (env==='DEVELOPMENT') {
                      queueType = 'activeMq';
                  }else{
                      queueType = 'WebSphereMq';
                  }
                  return new MessagingService(queueType);
              }];
        })
        .config(['MessagingServiceProvider', function(MessagingServiceProvider) {
            //Set the environment to a different value to see different behavior.
            MessagingServiceProvider.setEnvironment('DEVELOPMENT');
            //MessagingServiceProvider.setEnvironment('UAT');
        }])
        .controller('AppController', ['MessagingService', function(MessagingService) {
             var self = this;
             self.name='';
             self.message='';
             self.hello = function() {
                  self.message = MessagingService.sayHello(self.name);
             };
         
             self.bye = function(name) {
                  self.message = MessagingService.sayBye(self.name);
             };
         
        }]);  
        </script>
  </body>
</html>

Live Demo

In above provider setup, we have a provider with a set function, which can be used in module.config function to set some configuration. This updated configuration will eventually be used while creating the actual service instance. This instance will be created and returned via $get function. It’s the output from $get which will be injected into our controller.

4. Constant & Value

Angular provides us ways to define data that remains globally available while not really polluting the global namespace. Constant and Values are our options to define globally available data, which can be injected as a dependency into other service or controller.

Constant & Value are similar with few differences:

- A constant can be injected everywhere. The Value of a constant is not meant to be changed, and should never be changed.

var app = angular.module('myApp', []);

app.constant('PI', 3.14);

app.controller('AppController', ['PI', function(PI) {
    var self = this;
    self.r = 2;
    
    self.getArea = function(){
        return PI * r * r;
    }
}]);

- a Value can be changed. Unlike Constant, A value can not be injected into config phase of application.

var app = angular.module('myApp', []);

app.value('loggedinUser', 'SAM');

app.controller('AppController', ['loggedinUser', function(loggedinUser) {
    var self = this;
    self.message = 2;
    
    self.printMessage = function(){
        return 'Welcome '+loggedinUser;
    }
}]);

In above Value example, loggedinUser remain same for all the session, so it’s a good candidate to be declared as VALUE.

That’s it. In the next post AngularJS $http service example-server communication, we will develop a full-fledged live example for server communication using $http service. Stay tune.

If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help me improve further our learning process.

If you appreciate the effort I have put in this learning site, help me improve the visibility of this site towards global audience by sharing and linking this site from within and beyond your network. You & your friends can always link my site from your site on www.websystique.com, and share the learning.

After all, we are here to learn together, aren’t we?

  • Andrey Stepanov

    One more question please:
    regarding Const and Value…
    You mention that “a value can not be injected into config phase of application” and in your example “loggedinUser remain same for all the session, so it’s a good candidate to be declared as VALUE”

    If loggedinUser behaves like that why it is NOT a good candidate for CONST?

    And in your example loggedinUser is injected in exactly the same manner as PI injected in example above.
    So both examples look identical to me :( except for app.value(‘loggedinUser’, ‘SAM’) line

    Can you please clarify why and when do we need a Value?

    Thank you so much

    • websystique

      Hi Andrey, Both CONSTANT and VALUE refers to something which will remain fixed. They are conceptually different. The way i use them is that something should be declared as CONSTANT if it’s value is fixed and should not be changed in any circumstances [Value of PI is fixed, radius of earth is fixed]. On the other hand, if something is going to remain fixed in specific context and change in other, put is as a VALUE. LoggedInUser is the Logged-in user, which will differ for each user. Finally, no-one is stopping you putting loggedInUser as CONSTANT. You as a developer have a choice to decide which one[or both] fits your needs both programatically and conceptually.

  • Andrey Stepanov

    Hello, thank you for that wonderful tutorial which makes a lot of Angular concepts much clearer.

    Could you please explain what is the purpose of prefixing service attributes with ‘this’ and controller attributes with ‘self’?
    What is the difference between those two?
    I have seen (at Java Brains course on Angular for example) how controller properties have been prefixed with ‘this’ as well – when controller name was aliased. So can we use both of them whenever we want or just in specific cases?
    Thank you so much in advance

    • websystique

      Hi Andrey,
      It is preferable to use proxies like ‘self’ [or 'vm' as some people prefer] instead of using ‘this’ due to the fact that ‘this’ keyword in a javascript function can be overridden by anyone calling that function. Now on question of ‘self vs this’ in ‘controller & services’, you may want to use ‘self’ in both cases. I would also recommend Angular Coding Style Guide. Additionally, i would recommend you to have a look at this post which follows the coding guidelines mentioed in the previous link.

  • Pingback: AngularJS $http service example-server communication - WebSystique()

  • Pingback: AngularJS Form Validation Example - WebSystique()