In a well layered Angular application, the Controller layer should be very thin. In other words, most of the business logic and persistent data in the application should be placed in the Service.
Therefore, it is necessary to understand the differences between several providers in AngularJS.
New services created by the Provider can be used for injection. include:
* provider
* factory
* service
* constant
* value
In addition, the built-in services $controller and $filter can also be injected, and these services can also be used to obtain new filters and controllers.
The following describes their usage and the differences among provider, factory and value.
provider
It is used to generate a configurable Service, which consists of two parts. The variables and functions in the first part can be found in app The config function, you can modify them before they are accessed elsewhere. The definition is as follows:
app.provider('myProvider', function(){ var a = ''; var func = function(){}; })
On app The config function modifies a:
app.config(function(myProviderProvider){ myProvider.a = 'hello world'; })
This is also the reason for using a provider when there is such a simple factory.
The variables and functions in the second part are returned through the $get() function and can be accessed in any controller that passes in the provider.
app.provider('myProvider', function(){ this.$get = function(){ return { foo: function(){}, a: a } } })
factory
Factory returns an object. Just create an object, add properties to it, and then return the object. By injecting the factory into the controller, all its properties can be used.
app.factory('myFactory', function(){ var fac = {}; fac.a = 'hello world'; fac.foo = function(){}; return fac; })`
It can be seen that the second parameter of the factory is the function implementation corresponding to $get in the provider.
service
Service is similar to a constructor. Instantiate the object through the new keyword and add some properties and methods directly to this. When creating a service object, this will be returned as a return value.
app.service('myService', function(){ var a = ''; this.setA = function(){}; this.getA = function(){}; this.foo = function(){}; })
The controller injected into myService can access the seta (), geta () and foo() methods bound to this in myService.
constant
constant is used to define constants. Once defined, they cannot be changed. Can be injected anywhere, but cannot be decorated by decorators.
app.constant('APP_KEY', 'a1s2d3f4')
value
Like constant, it can be used to define values. But the difference from constant is that it can be modified, decorated by decorator, and cannot be injected into config.
app.value('version', '1.0')
Value is usually used to set the initial value for the application.
decorator
It's special. It's not a provider. It is used to decorate other providers, except constant, because it can be seen from the source code that constant is not created through the provider() method.
Below is a chestnut decorated with decorator.
app.value('version', '1.0'); app.decorator('version', function ($delegate) { return $delegate + '.1'; })
If you want to use the previous myService service, but it lacks a green function you want. Can I modify the service? The answer is no! But you can decorate it:
app.decorator('myService', function($delegate){ $delegate.greet = function(){ return "Hello, I am a new function of 'myService'"; } })
$delegate represents the actual service instance.
The ability to decorate a service is very practical, especially when we want to use a third-party service. At this time, we don't need to copy the code into our project, but only need to make some modifications.
Source code
The following is the underlying implementation of provider, factory, service, value, constant and decorator:
function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) { throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); } return providerCache[name + providerSuffix] = provider_; } function factory(name, factoryFn, enforce) { return provider(name, { $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn }); } function service(name, constructor) { return factory(name, ['$injector', function($injector) { return $injector.instantiate(constructor); }]); } function value(name, val) { return factory(name, valueFn(val), false); } function constant(name, value) { assertNotHasOwnProperty(name, 'constant'); providerCache[name] = value; instanceCache[name] = value; } function decorator(serviceName, decorFn) { var origProvider = providerInjector.get(serviceName + providerSuffix), orig$get = origProvider.$get; origProvider.$get = function() { var origInstance = instanceInjector.invoke(orig$get, origProvider); return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); }; }
It can be seen that apart from constant, the other final calls are all provider s (decorator s are special and do not count).
summary
When to use provider instead of factory?
Provider is an enhanced version of factory. When you need a configurable factory, use the provider.
Briefly introduce the application running process of AngularJS, which is divided into two stages: config stage and run stage. The config stage is the stage for setting any provider. It is also the stage of setting any instructions, controllers, filters and other things. In the run phase, AngularJS will compile your DOM and start the application.
What is the difference between factory and service?
Factory is a common function, while service is a constructor. In this way, Angular will use the new keyword when calling service, and when calling factory, it only calls a common function. Therefore, factory can return anything, while service can not return.