javascriptangularjsangular-strap

Angular JS factory vs service vs provider by example


I know this question has been asked and answers have been given. But I learn best through practical examples and I came across code that I didn't fully understand.

I'm referring to Angular Strap which is an awesome set of directives for cool user interactions: http://mgcrea.github.io/angular-strap/

I was looking at the code for the tooltip feature and saw that the author was using a provider to expose functionality. Could he have also used a service or a factory to do the same job? Or was a provider necessary?

Here is the link to the code: https://github.com/mgcrea/angular-strap/blob/master/src/tooltip/tooltip.js#L28

Thank you


Solution

  • Short answer: The author chose Provider to make the defaults 'read-only'. The code could still work if they hadn't used Provider, but Provider is cleaner and 'safer'

    Provider, Service, and Factory are all the same basic thing in Angular, just with different APIs; Provider can kinda be thought of as the 'base' element, but they all have the same end purpose: to create an Angular injectable. Each of those injectables has a Provider that provides the blueprint (Angular looks for a $get method), and a Singleton instance the provider generates. If you use Factory or Service, Angular does work behind the scenes so you don't need to know all the details; you'll just have a really boring Provider that only does the basics. However, if you use Provider yourself, you can put extra properties and functions on it in your declaration.

    You can inject Providers into a module's config() method, which is run before any of the Singletons are created. Try looking here for a longer explanation.

    In AngularStrap, the author puts a 'defaults' object on the Provider. The author expects you to modify that object in your module's config() method, and then Angular will generate the Singleton. However, the 'defaults' object is not on the Singleton, so you can't change the defaults once the app is 'running'. Even if you inject the Provider again somewhere and change 'default's again, Angular won't re-make your Singleton, so the defaults effectively become 'read-only'. This is a good practice to prevent code from making unwanted changes, especially when you have multiple people in the same code, or you know other people will be using your module.

    You may see other code that doesn't work like that... maybe another app just uses a factory, and puts the 'defaults' object on that factory. It would still 'work', and the code would look a lot like it does currently. However, because 'defaults' would be directly on the Singleton, your code could change these settings at ANY point if somebody wrote code to do it. Now you've got to leave comments and documentation explaining when to change the defaults, when NOT to change the defaults, and so on; for 99% of cases, the defaults never need to change once the app is running, so using Provider and module.config() is safe and straightforward.