Skip to content

Instantly share code, notes, and snippets.

@demisx
Last active December 26, 2024 05:39
Show Gist options
  • Save demisx/9605099 to your computer and use it in GitHub Desktop.
Save demisx/9605099 to your computer and use it in GitHub Desktop.
AngularJS Providers: Constant/Value/Service/Factory/Decorator/Provider
Provider Singleton Instantiable Configurable
Constant Yes No No
Value Yes No No
Service Yes No No
Factory Yes Yes No
Decorator Yes No? No
Provider Yes Yes Yes

Constant

A constant can be injected everywhere. A constant can not be intercepted by a decorator, that means that the value of a constant should never be changed (though it is still possible to change it programmatically in Angular 1.x).

angular.module('app', []);
 
app.constant('MOVIE_TITLE', 'The Matrix');
 
.controller('MyController', function (MOVIE_TITLE) {
  expect(MOVIE_TITLE).toEqual('The Matrix');
});

Value

A value is nothing more than a simple injectable value. The value can be a string, number but also a function. Value differs from constant in that value can not be injected into configurations, but it can be intercepted by decorators.

angular.module('app', []);

.value('movieTitle', 'The Matrix');

.controller('MyController', function (movieTitle) {
  expect(movieTitle).toEqual('The Matrix');
})

Service

Use Service when you need just a simple object such as a Hash, for example {foo:1, bar:2} It's easy to code, but you cannot instantiate it. A service is an injectable constructor. If you want you can specify the dependencies that you need in the function. A service is a singleton and will only be created once by AngularJS. Services are a great way for communicating between controllers like sharing data.

angular.module('app' ,[]);
 
.service('movie', function () {
  this.title = 'The Matrix';
});
 
.controller('MyController', function (movie) {
  expect(movie.title).toEqual('The Matrix');
});

Factory

A factory is an injectable function. A factory is a lot like a service in the sense that it is a singleton and dependencies can be specified in the function. The difference between a factory and a service is that a factory injects a plain function so AngularJS will call the function and a service injects a constructor. A constructor creates a new object so new is called on a service and with a factory you can let the function return anything you want. As you will see later on, a factory is a provider with only a $get method.

angular.module('app', []);
 
.factory('movie', function () {
  return {
    title: 'The Matrix';
  }
});
 
.controller('MyController', function (movie) {
  expect(movie.title).toEqual('The Matrix');
});
.factory('catalogueService', function($rootScope, $http) {
  // We first define a private API for our service.

  // Private vars.
  var items = [];

  // Private methods.
  function add( id ) {
    $http.put( $rootScope.apiURL, {id:id} )
    .success(function(data,status,headers,config) { items.push(data); })
    .then(function(response) { console.log(response.data); });
  }

  function store( obj ) {
    // do stuff
  }

  function remove( obj ) {
    // do stuff
  }

  // We now return a public API for our service.
  return {
    add: add,
    store: store,
    rm: remove
  };
};

Decorator

A decorator can modify or encapsulate other providers. There is one exception and that a constant cannot be decorated.

var app = angular.module('app', []);
 
app.value('movieTitle', 'The Matrix');
 
app.config(function ($provide) {
  $provide.decorator('movieTitle', function ($delegate) {
    return $delegate + ' - starring Keanu Reeves';
  });
});
 
app.controller('MyController', function (movieTitle) {
  expect(movieTitle).toEqual('The Matrix - starring Keanu Reeves');
});

#Provider A provider is the most sophisticated method of all the providers. It allows you to have a complex creation function and configuration options. A provider is actually a configurable factory. The provider accepts an object or a constructor.

var app = angular.module('app', []);
 
app.provider('movie', function () {
  var version;
  return {
    setVersion: function (value) {
      version = value;
    },
    $get: function () {
      return {
          title: 'The Matrix' + ' ' + version
      }
    }
  }
});
 
app.config(function (movieProvider) {
  movieProvider.setVersion('Reloaded');
});
 
app.controller('MyController', function (movie) {
  expect(movie.title).toEqual('The Matrix Reloaded');
});

Summary

  • All the providers are instantiated only once. That means that they are all singletons.
  • All the providers except constant can be decorated.
  • A constant is a value that can be injected everywhere. The value of a constant can never be changed.
  • A value is just a simple injectable value.
  • A service is an injectable constructor.
  • A factory is an injectable function.
  • A decorator can modify or encapsulate other providers except a constant.
  • A provider is a configurable factory.

Extracted from http://blog.xebia.com/2013/09/01/differences-between-providers-in-angularjs/

@edgar0011
Copy link

Hi,

I think you can instantiate VALUE and CONSTANT if those are functions,

module.constant("STATIC_LOGGER", function(){this.name = "logger"});
then somewhere:
var logger = new STATIC_LOGGER();
and same for .value.

Kind regards,

Edgar

@demisx
Copy link
Author

demisx commented Sep 16, 2014

Sure Edgar. Plain JavaScript kicks in here. I would, though, keep static logger in a factory service instead of a constant that returns a functions. I prefer to use constants for application-wide settings that I know won't change and that can also be injected in the module config phase. I follow these principles of code organization in Angular: http://demisx.github.io/angularjs/2014/09/14/angular-what-goes-where.html

@shahzadns
Copy link

Hey Dmitri ! Awesome post ! But "The value of a constant can never be changed." ?

angular.module( 'app',  [] )

 .constant( 'movie', {
  title: 'something'
 })

 .controller( 'firstCtrl', function ( $scope, movie ){
  $scope.setMovie = function ( newTitle ){
   movie.title = newTitle;
  };
 })

.controller( 'secondCtrl', function ( $scope, movie ){
  $scope.getMovie = function (){
   console.log( movie.title );
 };
 });

If you call setData() from firstCtrl View, and then call the getData from secondCtrl view, you would get the new value against constant 'movie'.

@mikael-georges
Copy link

@ShazadSoomro The goal of using constants is to never change their value and keep them as it is, a bit like having:

var APP_VERSION="1.0"

Regardless you found a way to alter their value, AFAIK constant have always been editable, we just don't change them once declared :)

If you wish to be able to change them use .value rather than .constant

@boyfunky
Copy link

I am currently facing a problem and since new to Angular. I need some more clarification on this. Does this mean that even if you changed your data in your service, the data still wont change because it has already been created? Because i created a factory service and i have removed all data from the function but it still returns the initial data in my controller. So does that means only the controller can be used then? What if i have a webservice that takes parameters to fetch data from an external source does it mean that even when the parameters change the results wouldnt change because it has already been created?

@mcblum
Copy link

mcblum commented Mar 28, 2015

Thank you. Thank you 1000.

@raghunandy
Copy link

Thank you ..

@chaddjohnson
Copy link

The difference between a factory and a service is that a factory injects a plain function so AngularJS will call the function and a service injects a constructor.

I think this is a confusing statement. When injecting a factory (.factory()), whatever the factory returns is injected (which could be a plain object or a plain function), but when injecting a service (.service()), an already-instantiated object is injected. Saying that a constructor is injected when injecting a service makes it seem like a constructor function itself is injected, and this is not the case.

@stackia
Copy link

stackia commented Aug 30, 2015

Thank you. Very helpful!

@surfbuds
Copy link

Agree with @chaddjohnson, it is confusing to say:

The difference between a factory and a service is that a factory injects a plain function so AngularJS will call the function and a service injects a constructor.

@houssemzaier
Copy link

Constants and providers are configurable, you can inject them into the config component.
Provider is the basic component that we can use to be a "service", then we can inject it into any controller.
The factory is a layer on top of the provider , we use it if we don't need to config a provider, it has a cleaner code to read.
The service is a layer on top of the factory we can use it when we need to use the "new" keyword provided by the Angular (you don't want to use that in many cases except OO inheritance ..).
We have 5 types of services in Angular:
1/Provider
2/Factory (it is a provider autoConfugurabe by Angular, if you create a factory called
" myFactory" Angular creates myFactoryProvider for you for free.)
3/Value (it is a factory that u can not inject into it, use it if you don't need to use built in services like $http, $scope... or any other service that you have created )
4/Service (it is a factory , that can use OO inheritance, imagine the scenario that you have a ParentService and some Services children that use some of the parents methods.. Do you really need that ?)
5/Constant (the most evident, it is not a provider but can be configurable, and injected like all those sevices into a controller ).
All of this services are singletons.

@dotku
Copy link

dotku commented May 4, 2016

'Value' actually can be configurated in app.config()

@thisismanish
Copy link

@dotku: We cannot inject 'Value' in config() block. So how we can configure 'Value'.????. If possible give me an example for this.

@thisismanish
Copy link

Can anybody clear out it that. I can modify 'constant' in controller as well 'value' in controller(I did it in live) either they are object or primitive. then what is exact diff. b/w them(except constant can inject in config block and value can't).

@davidshepherd7
Copy link

Nitpick: I think quite a few of your semicolons are wrong, e.g. where you have angular.module('app', []); followed by .value('movieTitle', 'The Matrix');

@calumjames
Copy link

A constant can be injected everywhere
That's not true. A constant can't be injected into another constant. I know you can't inject anything into a constant, but it might be worth pointing that out.

@NishantDesai1306
Copy link

@thisismanish, As mentioned by mikael-georges in commnets above, One can update both constant and value but the reason we have constant service is because it is a convention that value of constant services should not be changed.

Its just a convention just like in JSP _jspService() starts with an _ because it tells that a developer that he/she should not override it.
Hope This helps.

@runesam
Copy link

runesam commented Jan 25, 2017

thanks a lot man 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment