Friday, May 24, 2013

Angular service or factory?

tl;dr is at the end

In various AngularJS tutorials and documentation, the authors choose to use service or factory but don't explain why you would use one or the other. Few mention that value and constant are also options.

Let's see why you would use one over the other. We should also understand how providers work:

provider

Here's the source for the provider method:

function provider(name, provider_) {
if (isFunction(provider_) || isArray(provider_)) {
provider_ = providerInjector.instantiate(provider_);
}
if (!provider_.$get) {
throw Error('Provider ' + name + ' must define $get factory method.');
}
return providerCache[name + providerSuffix] = provider_;
}

name is a string. provider_ can be one of three things:

  1. function

    If a function is passed in, the function is called with dependency injection and should return an object with a $get method.

  2. array

    An array will be treated like a function using Inline Annotation. It must also return an object with a $get method.

  3. object

    If an object is passed in, it is simply expected to have a $get method.

Whatever the second arg to provider is, you eventually end up with an object that has a $get method. Here's an example showing what happens:

// You can run this

// Create a module
var hippo = angular.module('hippo', []);

// Register an object provider
hippo.provider('awesome', {
$get: function() {
return 'awesome data';
}
});

// Get the injector (this happens behind the scenes in angular apps)
var injector = angular.injector(['hippo', 'ng']);

// Call a function with dependency injection
injector.invoke(function(awesome) {
console.log('awesome == ' + awesome);
});

Once you understand providers you will see that factory, service, value and constant are just convenience methods for making providers.

factory

Here's the source:

function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}

So it lets you shorten the awesome provider creation code to this:

hippo.factory('awesome', function() {
return 'awesome data';
})

service

Here's the source:

function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}

So it lets you make a factory that will instantiate a "class". For example:

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

function Gandalf() {
this.color = 'grey';
}
Gandalf.prototype.comeBack = function() {
this.color = 'white';
}

gandalf.service('gandalfService', Gandalf);

var injector = angular.injector(['gandalf', 'ng']);

injector.invoke(function(gandalfService) {
console.log(gandalfService.color);
gandalfService.comeBack()
console.log(gandalfService.color);
});

The above code will instantiate Gandalf, but remember that everything that uses the service will get the same instance! (which is a good thing).

value

Here's the source:

function value(name, value) {
return factory(name, valueFn(value));
}

Using value would let you shorten the awesome provider to:

hippo.value('awesome', 'awesome data');

constant

Here's the source

function constant(name, value) {
providerCache[name] = value;
instanceCache[name] = value;
}

constant differs from value in that it's accessible during config. Here's how you use it:

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

joe.constant('bobTheConstant', 'a value');
joe.value('samTheValue', 'a different value');

joe.config(function(bobTheConstant) {
console.log(bobTheConstant);
});

joe.config(function(samTheValue) {
console.log(samTheValue);
});

// This will fail with "Error: Unknown provider: samTheValue from joe"
var injector = angular.injector(['joe', 'ng']);

Read Module Loading & Dependencies in the Modules doc for more information on usage.

In summary

If you want your function to be called like a normal function, use factory. If you want your function to be instantiated with the new operator, use service. If you don't know the difference, use factory.

This is the (great) documentation for each function in the AngularJS source:

  1. factory

    A short hand for configuring services if only `$get` method is required.

  2. service

    A short hand for registering service of given class.

  3. value

    A short hand for configuring services if the `$get` method is a constant.

  4. constant

    A constant value, but unlike {@link AUTO.$provide#value value} it can be injected into configuration function (other modules) and it is not interceptable by {@link AUTO.$provide#decorator decorator}.

28 comments:

  1. I'm going to read later, because I love all things Angular these days. But I just had to comment on your blog design. It's freaking cool. Nice job.

    ReplyDelete
  2. https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ

    ReplyDelete
  3. Nice little article, I would differ however, and say, if you don't know the difference between calling 'like a regular function' and using the new operator: You should figure out the difference first, and then not just blindly pick factory.

    ReplyDelete
    Replies
    1. So what IS the difference? I don't see why it matters.

      Delete
    2. Sorry it's taken me so long. In the way I generally use `factory`, there wouldn't be a significant difference if I used `service` instead. But if I wanted to use a javascript "class" (by adding methods to a prototype object), then I would need to use `service.`

      Here's more discussion about what "new" does: http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript

      Delete
    3. Learn by doing: Use the Factory pattern until you find a need to use Service (such as when you're reusing existing OOP classes from prior JavaScript models).

      Delete
  4. Great article, makes all these little helper methods so much more transparent.

    ReplyDelete
  5. I think there's an error in the service source. It says factory where it should say provider. I hope I'm right, otherwise I'm confused...

    ReplyDelete
    Replies
    1. Jacco,

      A service is a specific kind of factory: one that instantiates the function instead of just calling it.

      See https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js Search for "function service("

      Delete
  6. Great article. Really loved it. Very clear and very informative. =) Your "use the source" approach is awesome. I hope you keep them (angularjs articles) coming. I need them! =D
    Thank you.

    ReplyDelete
  7. ye its a very impresive article about in a services in factory.i really like that.thanks for sharing such a nice blog.IT services

    ReplyDelete
  8. Nice article on angular services.i really like your all points.fantastic going.keep posting in fututre.IT services

    ReplyDelete
  9. A grate documentation and awesome article. AngularJS works great with other technologies. Add as much or as little of AngularJS to an existing page as you like. Many other frameworks require full commitment. This page has multiple AngularJS applications embedded in it, read more.

    ReplyDelete
  10. Your post says ..."The above code will instantiate Gandalf, but remember that everything that uses the service will get the same instance! (which is a good thing)."
    And then, at the end it says,
    "If you want your function to be instantiated with the new operator, use service"

    So, by using a service, do I get a new instance or the same old instance ?
    Because, if the method is instantiated each time, then it must give a diff instance right ?

    ReplyDelete
    Replies
    1. Using service, you will get the same instance each time. Run the example gandalf code, then run this:

      injector.invoke(function(gandalfService) {
      console.log(gandalfService.color);
      });

      You will see that his color is still white (and not grey as it would be with a new instance).

      Delete
  11. It is non clear to me what the method $get must be. Let me know if i get it right: the $get method is a (annotated) function whose return value (object, function or primitive type) is what we get when we use the service. In the case of service there is no $get method, instead we pass a constructor which constructs the object we get when we use the service (in this case we can only use an object, not a function or a primitive value)

    ReplyDelete
  12. Great article, now I Understand it!

    ReplyDelete
  13. This is the article I've been searching for, for about a week now. Thanks you so much!

    ReplyDelete
  14. This comment has been removed by a blog administrator.

    ReplyDelete
  15. Clear explanation, thank you... and awesome blog design !!!

    ReplyDelete
  16. A Service is good for providing cross app/controller communication. A very good presentation on http://slides.wesalvaro.com/20121113/#/2/3

    ReplyDelete
  17. The in summary should be at the top so the rest of the code makes sense. Love this ty!

    ReplyDelete
  18. Is the point of difference then that a factory is for multiple instances and a service for a singleton? Is that it (other than the subtle syntax differences of course)

    ReplyDelete
    Replies
    1. Both factory and service make singletons. The only difference is that service is instantiated as a JavaScript "class."

      Delete
  19. Problem: HP Printer not connecting to my laptop.
    I had an issue while connecting my 2 year old HP printer to my brother's laptop that I had borrowed for starting my own business. I used a quick google search to fix the problem but that did not help me.
    I then decided to get professional help to solve my problem. After having received many quotations from various companies, i decided to go ahead with Online Tech Repair (www.onlinetechrepairs.com).
    Reasons I chose them over the others:
    1) They were extremely friendly and patient with me during my initial discussions and responded promptly to my request.
    2) Their prices were extremely reasonable.
    3) They were ready and willing to walk me through the entire process step by step and were on call with me till i got it fixed.
    How did they do it
    1) They first asked me to state my problem clearly and asked me a few questions. This was done to detect any physical connectivity issues with the printer.
    2) After having answered this, they confirmed that the printer and the laptop were functioning correctly.
    3) They then, asked me if they could access my laptop remotely to troubleshoot the problem and fix it. I agreed.
    4) One of the tech support executives accessed my laptop and started troubleshooting.
    5) I sat back and watched as the tech support executive was navigating my laptop to spot the issue. The issue was fixed.
    6) I was told that it was due to an older version of the driver that had been installed.
    My Experience
    I loved the entire friendly conversation that took place with them. They understood my needs clearly and acted upon the solution immediately. Being a technical noob,

    sometimes find it difficult to communicate with tech support teams. It was a very different experience with the guys at Online Tech Repairs. You can check out their website www.onlinetechrepairs.com or call them on 1-914-613-3786.
    Would definitely recommend this service to anyone who needs help fixing their computers.
    Thanks a ton guys. Great Job....!!

    ReplyDelete
  20. VIRUS REMOVAL

    Is Your Computer Sluggish or Plagued With a Virus? – If So you Need Online Tech Repairs
    As a leader in online computer repair, Online Tech Repairs Inc has the experience to deliver professional system optimization and virus removal.Headquartered in Great Neck, New York our certified technicians have been providing online computer repair and virus removal for customers around the world since 2004.
    Our three step system is easy to use; and provides you a safe, unobtrusive, and cost effective alternative to your computer service needs. By using state-of-the-art technology our computer experts can diagnose, and repair your computer system through the internet, no matter where you are.
    Our technician will guide you through the installation of Online Tech Repair Inc secure software. This software allows your dedicated computer expert to see and operate your computer just as if he was in the room with you. That means you don't have to unplug everything and bring it to our shop, or have a stranger tramping through your home.
    From our remote location the Online Tech Repairs.com expert can handle any computer issue you want addressed, like:
    • - System Optimization
    • - How it works Software Installations or Upgrades
    • - How it works Virus Removal
    • - How it works Home Network Set-ups
    Just to name a few.
    If you are unsure of what the problem may be, that is okay. We can run a complete diagnostic on your system and fix the problems we encounter. When we are done our software is removed; leaving you with a safe, secure and properly functioning system. The whole process usually takes less than an hour. You probably couldn't even get your computer to your local repair shop that fast!
    Call us now for a FREE COMPUTER DIAGONISTIC using DISCOUNT CODE (otr214428@gmail.com) on +1-914-613-3786 or chat with us on www.onlinetechrepairs.com.

    ReplyDelete
  21. We are a leading software development services in delhi,which works as per the client requirements and give provide software.

    ReplyDelete