How to create (singleton) AngularJS services in 4 different ways

Next to creating controllers and directives, AngularJS also supports “singleton” services.
Services, like on the server-side, offer a great way for separating logic from your controllers.

In AngularJS anything that’s either a primitive type, function or object can be a service.

Although the concept of service is quite straight forward, the declaration of them in AngularJS isn’t:

  • There are 4 different ways to declare a service.
    • Registering a existing value as a service
    • Registering a factory function to create the singleton service instance
    • Registering a constructor function to create the singleton service instance
    • Registering a service factory which can be configured
  • Only 1 of them is extensively documented

The other 3 are only barely documentedThis post describes each option and when to use it in more detail.

Registering a existing value as a service

You can register an existing value as service, using the following methods of the Module type:

  • constant(name, value)“. intended for registering configuration data and should therefore only be used with primitives or object containing just data.
  • value(name, value)“: registers a primitive, existing object instance or function.
    The big difference between the “constant” and “value” methods is that: 

    • “constant” should only be used for… constants.
    • services registered with “value” as well as the 3 other ways can even be proxied.

Consider the following example using both styles:

Registering a factory function to create the singleton service instance

Instead of supplying an existing value, you could also register a factory function for the service.
However since services in AngularJS are “singletons” the factory function is invoked once.
A factory function can optionally take parameters which, just like controllers and directives, which will be injected by AngularJS.

Using the earlier registered magicNumber ‘service’, you can now declare a service using the “factory(name, providerFunction)” (extensively documented) method:

Registering a constructor function to create the singleton service instance

Instead of registering a factory function that returns an instance of a service,
you could also register a constructor function for your service object using the
service(name, constructor)” method:

Registering a service factory which can be configured

Last but not least… there is way more advanced way to register a service factory using  “provider(name, providerType)” which can be configured used the “Module#config(configFn)” .

Using the “provider(name, providerType)” you can register a so-called “providerType”.
This “providerType” can be either an existing object or a constructor function containing:

  • any number of configuration methods (i.e. “setMagicNumber”)
  • a “$get” factory function just like the one used with “factory(name, providerFunction)

Using “provider(name, providerType)” we can make our service configurable:

To allow configuration each service registered with ”provider(name, providerType)” automatically gets a “special” additional service with the “Provider” postfix.
This special “…Provider” service (i.e. “magicNumberServiceProvider”) can be used solely in combination with “Module#config(configFn)” to configure the service prior to its construction:

When should you use which way?

There is no right or wrong when it comes the various way in which you can register a service.
Some might argue that “factory(name, providerFunction)” would be preferable since it’s extensively documented.
Others would prefer registering existing service instances using “value(name, value)“.

To ease choosing between the 4 different ways I will shortly recap all of them:

  • Use either “value(name, value)” or “constant(name, value)” to register an existing value:
    • you typically would use “value” to register a service object or a function
    • whereas “constant” should only be used for configuration data
  • factory(name, providerFunction)“: registers a factory function responsible for creating the “singleton” service instance.
    Just like “value(name, value)” a factory function could return anything from primitive type, function or object instance.
  • service(name, constructor)“: registers the constructor function which will be constructed using a “new” keyword.
  • provider(name, providerType)“: the most advanced way to register a service.
    Most often there is no need for your service to be configurable through a “…Provider” service, unless you are writing a reusable JavaScript library containing AngularJS services.

References

 

19 thoughts on “How to create (singleton) AngularJS services in 4 different ways

  1. Pingback: AngularJS学习资源列表 | 天天三国杀

  2. Pingback: AngularJS - Beginners guide / Yoosuf Muhammad

  3. Pingback: Currently Open Tabs: Resources For Using AngularJS - Anti-Code.com

  4. Pingback: angularjs 学习大礼包大赠送【权威英文版】! _ Angular _ 小G的大Q

  5. Your examples are confusing since you use the same code to define a constructor function and then when you register it for the factory you construct it.

    • Thank you for your useful comment… I just changed the code example to make it (hopefully) less confusing.

  6. In the section ‘Registering a service factory which can be configured’,

    app.provider(name, providerType): helps to register a service.

    How do we inject the dependencies such as $q, $rootScope, etc?

    • Aravind,

      As it turned out my usage sample of “Module#provider” did actually contain an error (which I just corrected) which might have caused some confusion.

      The “$get” (factory) function can be injected just like other AngularJS code.
      Since at first I wasn’t completely sure of this myself I just created a Plunk based of the (corrected) “Module#provider” usage sample from the blog post that proofs that is works (check the console log to see that $q is injected):
      http://plnkr.co/edit/AnwHRE3khBUMPX4AuCLp?p=preview

      Kind regards,

      Emil

  7. This is a very good article, certainly help me understand the differences. The only suggestion I would make is to add a concrete/real world example for when you would use each type.

    • Thank you for your suggestion… reading back my blog post I have to agree to some parts would me more descriptive with some real world examples.
      Additionally I’m thinking of explaining “$provide” and the fact that Module#constant was also be wired into the Module#config function.

  8. Pingback: AngularJS Service, Factory, Provider diff | gelistirme.org

  9. Pingback: Having trouble creating a Singleton AngularJS Service | Technology & Programming

  10. Pingback: AngularJS-Learning | Nisar Khan

  11. Pingback: Learning AngularJS – best resources to learn angularjs for beginners. | Bhavin Patel

  12. Pingback: AngularJS – Beginners guide | Bhavin Patel

  13. Pingback: AngularJS – Service VS Factory VS Provider | Eureka!

  14. Pingback: How could you become zero to hero in AngularJS? | Milap Bhojak

  15. Pingback: AngularJS Provider Multiple Instance | Alonso

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">