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: /
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: .js#L28
Thank you
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./mgcrea/angular-strap/blob/master/src/tooltip/tooltip.js#L28
Thank you
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Feb 12, 2015 at 1:32 ShazShaz 2,7041 gold badge22 silver badges22 bronze badges 2- Already responded here: stackoverflow./questions/14324451/… ;) – Jean-Baptiste Louazel Commented Feb 12, 2015 at 2:30
- In this case, they DO get a concrete advantage by using Provider; see my answer – Hylianpuffball Commented Feb 12, 2015 at 2:44
4 Answers
Reset to default 4While the documentation is correct that there are special cases to use each I think it's also important to answer that they are all the same thing.
The factory
is a specialized version of provider
that in some cases let's you acplish the same thing using less code. In turn a service
and value
are special cases of factory
. And constant
is a special case of value
.
Here is an image that shows you at a glance what I mean:
(source: simplygoodcode.)
You can get more details on the blog the image is from: http://www.simplygoodcode./2015/11/the-difference-between-service-provider-and-factory-in-angularjs/
There's also another question on Stack Overflow with similiar details at: https://stackoverflow./a/33805462/984780
According to the official Angular Documentation:
There are five recipe types.
The most verbose, but also the most prehensive one is a Provider recipe. The remaining four recipe types — Value, Factory, Service and Constant — are just syntactic sugar on top of a provider recipe.
So, in essence, building a Service and building a Provider are identical, assuming you don't need to access some of the advanced settings. They go on to say:
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts.
and here is a table:
Features / Recipe type
Factory Service Value Constant Provider can have dependencies yes yes no no yes uses type friendly injection no yes yes* yes* no object available in config phase no no no yes yes** can create functions yes yes yes yes yes can create primitives yes no yes yes yes* at the cost of eager initialization by using new operator directly
** the service object is not available during the config phase, but the provider instance is.
Angular provides us with three ways to create and register our own service.
Factory
Service
Provider
1. Factory : When you’re using a Factory you create an object, add properties to it, then return that same object. When you pass this service into your controller, those properties on the object will now be available in that controller through your factory.
Example :
app.controller('myFactoryCtrl', function ($scope, myFactory) {
$scope.artist = myFactory.getArtist()
});
app.factory('myFactory', function () {
var _artist = '';
var service = {}
service.getArtist = function () {
return _artist
}
return service;
});
2 Service: When you’re using Service, it’s instantiated with the ‘new’ keyword. Because of that, you’ll add properties to ‘this’ and the service will return ‘this’. When you pass the service into your controller, those properties on ‘this’ will now be available on that controller through your service.
Example :
app.controller('myServiceCtrl', function ($scope, myService) {
$scope.artist = myService.getArtist();
});
app.service('myService', function () {
var _artist = '';
this.getArtist = function () {
return _artist;
}
});
3 Provider : Providers are the only service you can pass into your .config() function. Use a provider when you want to provide module-wide configuration for your service object before making it available.
Example :
app.controller('myProviderCtrl', function ($scope, myProvider) {
$scope.artist = myProvider.getArtist();
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
app.provider('myProvider', function () {
this._artist = '';
this.thingFromConfig = '';
//Only the properties on the object returned from $get are available in the controller.
this.$get = function () {
var that = this;
return {
getArtist: function () {
return that._artist;
},
thingonConfig: that.thingFromConfig
}
}
});
app.config(function (myProviderProvider) {
myProviderProvider.thingFromConfig = 'This was set in config()';
});
To read more about services click here
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 bee '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 ments 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.