SlideShare una empresa de Scribd logo
1 de 18
AngularJS. An overview of the
$provide’s API and $injector.
Yan Yankowski

Differences between
providers, factories, services, values,
constants, and decorators.
createInjector Method
•

providerCache – contains references to instantiated providers (after the body
function of the provider has been invoked as the provider’s constructor). All
custom factories and services in the application will be converted to providers and
registered here on application start. When the providerCache object is created it
always has $provide as the 1-st cached provider. This providerCache object also
has constants cached.
The $get method
hasn’t been
invoked.
• instanceCache – all instantiated providers (i.e.
whose method $get has been called) and
constants will be cached here for further
reusage.
A logManagerProvider’s $get
method has already been
invoked. Hence we see here
an instantiated service
object providing logging
functionality.
createInternalInjector Method
• How the provider is instantiated
1

providerCache

2

Important!
At this stage providerCache
dictionary is used by the
getService method.

The algorithm of the instantiation:
1.
Check whether the provider is already
instantiated (saved in the providerCache). If yes –
return it from the cache. Normally all the
providers defined in the application are already
there at this point.
2.
If the value in the cache points to the
INSTANTIATING token, then we are inside the
instantiation process of a dependency of some
other parentModule . The problem is that we are
also dependent on the parentModule and trying
to instantiate it as well. A chicken and an egg
problem.
3.
If no instance is found in the providerCache then
the exception will be thrown upon accessing the
key. It usually means that either the required
dependency is not provided or the js-file is not
included.

3
function() {
throw Error("Unknown provider: " + path.join(' <- '));
}
• How the instance of a service object is created
Important!
At this stage instanceCache
dictionary is used by the
getService method.

1
instanceCache

The algorithm of the instantiation:
1.

Check whether the instance is already
created (saved in the instanceCache). If yes –
return it from the instanceCache.
If the value in the cache points to the
INSTANTIATING token, then some other
service is simultaneously trying to instantiate
given object.
If no instance is found in the instanceCache
then the factory function takes the
responsibility of instantiating the object. The
instance is then cached.

2.

2

3.

3

The invoke method pipes the dependency names of the service,
instantiates each one of them with the getService method, then
loads the instantiated dependencies into the args array, iterates
over the args array and calls the provider body function, passing
it each dependency as a parameter.

function(servicename) {
var provider = providerInjector.get(servicename
+providerSuffix);
return instanceInjector.invoke(provider.$get, provider);
}
Provider
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_;
}

•
•

The name parameter is a string containing the name of the provider
The provider_ parameter must be one of the following three types:
1.
2.
3.

A function that returns an object with a $get method.
An array. In this case the last element of this array is always a function (cf. 1-st item of the list) or an object which has the $get method. All
the previous items of the array are treated as arguments to be injected upon the provider instantiation.
An object containing the method $get.
• Points of interest:
1) must define $get method (which in its turn
returns a factory/service object inside itself);
2) Uses providerInjector to retrieve its instance
(calls getService method internally, which in
it’s turn retrieves the instance of the provider
from the providerCache);
3) Once the $get method has been invoked the
instanceInjector will be used to retrieve the
instance of the created service object (from
instanceCache).
Factory
function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
The factory defines the body for the $get method of the underlying provider. We can see it by
looking at the above code block. Internally factory calls the provider registration method of the
$provide object, basically being a wrapper over it.
Service
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}

• uses $injector for instantiation;
• uses constructor function for instantiation – it
means that the service function is treated as a
constructor;
• When do I prefer Service to Factory ?
The service is preferable when you want to
define a constructor function to be instantiated
with new.
angular.service(“MyService”, function (){
this.foo;
});
Or
angular.service(“MyService”, MyConstructorFunction);

function MyConstructor(){ this.value }
MyConstructor.prototype.someFunction =
function(){ }

Will eventually be instantiated as :
$injector.instantiate(function (){
this.foo;
});
OR
new (function (){
this.foo;
});
So what is the main difference
between the Factory and the Service?
• Factory wrapper returns an instance of an
object.
• Service wrapper defines a constructor of an
object. This constructor will be later used to
instantiate a return object by the factory.
Value
function value(name, value) { return factory(name, valueFn(value)); }

function valueFn(value) {return function() {return value;};}
•

From the above code we see that the value method is a wrapper over factory
method. Hence a value is just one more layer over a provider registration method.

When to use?
• when you don’t need complicated logic and encapsulation;
• when you want to provide simple object for further injection.
Constant
function constant(name, value) {
providerCache[name] = value;
instanceCache[name] = value;
}

Important!
Both providerCache[constantName] and
instanceCache[constantName] point to
the same instance, which means that the
constant is equally usable during the
config and run stages..

• The constant object value can be accessed and used
during the configuration phase of the application. The
method $get of the providers hasn’t yet been called at
this stage, but the constants don’t need $get to be
called – they are already fully instantiated. So the
constants are the only objects inside the application
scope able to provide custom functionality at this
stage.
• When the application is started a new
instance of the constant object is placed into
providerCache and instanceCache (since no
call to the method $get is needed) .
The constant object
is fully available on
the application
configuration stage.
Good to know that …

•

•

The constant object is not interceptable by the decorator since it
lacks the $get function!
In the Jasmine testing framework using angular mock lib the mock
of the constant is created by using $provide.constant() method.
Decorator
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});
};
}

Get the provider to be
decorated
Save reference to
the original $get
method
Wrap the original
$get method
inside a new one.

• Use decorator to add functionality to the
existing services. Useful in cases when new
functionality has to be added into core
AngularJS services without touching the
source.
What exactly leads to circular
dependency exception.
• Suppose we have the following code:
window.mainApp = angular.module("mainApp", []);
mainApp.run(["mainLogger", function (mainLogger) {
mainLogger.log();
}]);
mainApp.service("mainLogger", [" secondaryLogger", function (secondaryLogger) {
this.log = function() {
console.log(); };
}]);
mainApp.service("secondaryLogger", ["mainLogger", function (mainLogger) {
this.log = function () { console.log(); };
}]);

Both services here are dependent on each other.
When a new service
(mainLogger) is
registered, its name is
first inserted as a key
into instanceCache
with the value pointing
to the INSTANTIATING
token. No actual
provider object is yet
created.

AngularJS then proceeds to creating mainLoggerProvider object: registers it in the providerCache. The
framework detects that the service has a dependency on secondaryLogger service. To resolve this dependency it
needs to create a secondaryLoggerProvider object, register it in the providerCache, and call its $get method in
order to create an instance of the secondaryLogger service (to inject into mainLoggerProvider). At this point the
framework sees the dependency on mainLoggerProvider and honestly tries to get it from the instanceCache or
to instantiate it. As we remember it is already in the instanceCache dictionary still pointing to the INSTANTIATING
token. Exception follows…

Más contenido relacionado

La actualidad más candente

Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
Wei Ru
 

La actualidad más candente (20)

AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS Directives
 
Modules and injector
Modules and injectorModules and injector
Modules and injector
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
AngularJS Framework
AngularJS FrameworkAngularJS Framework
AngularJS Framework
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Angularjs Basics
Angularjs BasicsAngularjs Basics
Angularjs Basics
 
Angular 2.0 Dependency injection
Angular 2.0 Dependency injectionAngular 2.0 Dependency injection
Angular 2.0 Dependency injection
 
AngularJS Services
AngularJS ServicesAngularJS Services
AngularJS Services
 
Template syntax in Angular 2.0
Template syntax in Angular 2.0Template syntax in Angular 2.0
Template syntax in Angular 2.0
 
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
 
Performance Optimization In Angular 2
Performance Optimization In Angular 2Performance Optimization In Angular 2
Performance Optimization In Angular 2
 
Angular js routing options
Angular js routing optionsAngular js routing options
Angular js routing options
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
 
Building an End-to-End AngularJS Application
Building an End-to-End AngularJS ApplicationBuilding an End-to-End AngularJS Application
Building an End-to-End AngularJS Application
 
Routing And Navigation
Routing And NavigationRouting And Navigation
Routing And Navigation
 
Http Communication in Angular 2.0
Http Communication in Angular 2.0Http Communication in Angular 2.0
Http Communication in Angular 2.0
 
Workshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte IIIWorkshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte III
 
Angular 2.0 Routing and Navigation
Angular 2.0 Routing and NavigationAngular 2.0 Routing and Navigation
Angular 2.0 Routing and Navigation
 

Similar a AngularJs $provide API internals & circular dependency problem.

J2EE : Java servlet and its types, environment
J2EE : Java servlet and its types, environmentJ2EE : Java servlet and its types, environment
J2EE : Java servlet and its types, environment
joearunraja2
 

Similar a AngularJs $provide API internals & circular dependency problem. (20)

ngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency InjectionngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency Injection
 
How to perform debounce in react
How to perform debounce in reactHow to perform debounce in react
How to perform debounce in react
 
AngularJs-training
AngularJs-trainingAngularJs-training
AngularJs-training
 
"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović
 
Servlet11
Servlet11Servlet11
Servlet11
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgets
 
Appcelerator Titanium Alloy + Kinvey Collection Databinding - Part One
Appcelerator Titanium Alloy + Kinvey Collection Databinding - Part OneAppcelerator Titanium Alloy + Kinvey Collection Databinding - Part One
Appcelerator Titanium Alloy + Kinvey Collection Databinding - Part One
 
Spring Batch in Code - simple DB to DB batch applicaiton
Spring Batch in Code - simple DB to DB batch applicaitonSpring Batch in Code - simple DB to DB batch applicaiton
Spring Batch in Code - simple DB to DB batch applicaiton
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
 
Servlet
ServletServlet
Servlet
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
 
Testing React hooks with the new act function
Testing React hooks with the new act functionTesting React hooks with the new act function
Testing React hooks with the new act function
 
J2EE : Java servlet and its types, environment
J2EE : Java servlet and its types, environmentJ2EE : Java servlet and its types, environment
J2EE : Java servlet and its types, environment
 
Http programming in play
Http programming in playHttp programming in play
Http programming in play
 
Reactive programming with RxJava
Reactive programming with RxJavaReactive programming with RxJava
Reactive programming with RxJava
 
Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0
 
Describe's Full of It's
Describe's Full of It'sDescribe's Full of It's
Describe's Full of It's
 
Rmi
RmiRmi
Rmi
 
Introduction to nsubstitute
Introduction to nsubstituteIntroduction to nsubstitute
Introduction to nsubstitute
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Último (20)

Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 

AngularJs $provide API internals & circular dependency problem.

  • 1. AngularJS. An overview of the $provide’s API and $injector. Yan Yankowski Differences between providers, factories, services, values, constants, and decorators.
  • 2. createInjector Method • providerCache – contains references to instantiated providers (after the body function of the provider has been invoked as the provider’s constructor). All custom factories and services in the application will be converted to providers and registered here on application start. When the providerCache object is created it always has $provide as the 1-st cached provider. This providerCache object also has constants cached. The $get method hasn’t been invoked.
  • 3. • instanceCache – all instantiated providers (i.e. whose method $get has been called) and constants will be cached here for further reusage. A logManagerProvider’s $get method has already been invoked. Hence we see here an instantiated service object providing logging functionality.
  • 4. createInternalInjector Method • How the provider is instantiated 1 providerCache 2 Important! At this stage providerCache dictionary is used by the getService method. The algorithm of the instantiation: 1. Check whether the provider is already instantiated (saved in the providerCache). If yes – return it from the cache. Normally all the providers defined in the application are already there at this point. 2. If the value in the cache points to the INSTANTIATING token, then we are inside the instantiation process of a dependency of some other parentModule . The problem is that we are also dependent on the parentModule and trying to instantiate it as well. A chicken and an egg problem. 3. If no instance is found in the providerCache then the exception will be thrown upon accessing the key. It usually means that either the required dependency is not provided or the js-file is not included. 3 function() { throw Error("Unknown provider: " + path.join(' <- ')); }
  • 5. • How the instance of a service object is created Important! At this stage instanceCache dictionary is used by the getService method. 1 instanceCache The algorithm of the instantiation: 1. Check whether the instance is already created (saved in the instanceCache). If yes – return it from the instanceCache. If the value in the cache points to the INSTANTIATING token, then some other service is simultaneously trying to instantiate given object. If no instance is found in the instanceCache then the factory function takes the responsibility of instantiating the object. The instance is then cached. 2. 2 3. 3 The invoke method pipes the dependency names of the service, instantiates each one of them with the getService method, then loads the instantiated dependencies into the args array, iterates over the args array and calls the provider body function, passing it each dependency as a parameter. function(servicename) { var provider = providerInjector.get(servicename +providerSuffix); return instanceInjector.invoke(provider.$get, provider); }
  • 6. Provider 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_; } • • The name parameter is a string containing the name of the provider The provider_ parameter must be one of the following three types: 1. 2. 3. A function that returns an object with a $get method. An array. In this case the last element of this array is always a function (cf. 1-st item of the list) or an object which has the $get method. All the previous items of the array are treated as arguments to be injected upon the provider instantiation. An object containing the method $get.
  • 7. • Points of interest: 1) must define $get method (which in its turn returns a factory/service object inside itself); 2) Uses providerInjector to retrieve its instance (calls getService method internally, which in it’s turn retrieves the instance of the provider from the providerCache); 3) Once the $get method has been invoked the instanceInjector will be used to retrieve the instance of the created service object (from instanceCache).
  • 8. Factory function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } The factory defines the body for the $get method of the underlying provider. We can see it by looking at the above code block. Internally factory calls the provider registration method of the $provide object, basically being a wrapper over it.
  • 9. Service function service(name, constructor) { return factory(name, ['$injector', function($injector) { return $injector.instantiate(constructor); }]); } • uses $injector for instantiation; • uses constructor function for instantiation – it means that the service function is treated as a constructor;
  • 10. • When do I prefer Service to Factory ? The service is preferable when you want to define a constructor function to be instantiated with new. angular.service(“MyService”, function (){ this.foo; }); Or angular.service(“MyService”, MyConstructorFunction); function MyConstructor(){ this.value } MyConstructor.prototype.someFunction = function(){ } Will eventually be instantiated as : $injector.instantiate(function (){ this.foo; }); OR new (function (){ this.foo; });
  • 11. So what is the main difference between the Factory and the Service? • Factory wrapper returns an instance of an object. • Service wrapper defines a constructor of an object. This constructor will be later used to instantiate a return object by the factory.
  • 12. Value function value(name, value) { return factory(name, valueFn(value)); } function valueFn(value) {return function() {return value;};} • From the above code we see that the value method is a wrapper over factory method. Hence a value is just one more layer over a provider registration method. When to use? • when you don’t need complicated logic and encapsulation; • when you want to provide simple object for further injection.
  • 13. Constant function constant(name, value) { providerCache[name] = value; instanceCache[name] = value; } Important! Both providerCache[constantName] and instanceCache[constantName] point to the same instance, which means that the constant is equally usable during the config and run stages.. • The constant object value can be accessed and used during the configuration phase of the application. The method $get of the providers hasn’t yet been called at this stage, but the constants don’t need $get to be called – they are already fully instantiated. So the constants are the only objects inside the application scope able to provide custom functionality at this stage.
  • 14. • When the application is started a new instance of the constant object is placed into providerCache and instanceCache (since no call to the method $get is needed) . The constant object is fully available on the application configuration stage.
  • 15. Good to know that … • • The constant object is not interceptable by the decorator since it lacks the $get function! In the Jasmine testing framework using angular mock lib the mock of the constant is created by using $provide.constant() method.
  • 16. Decorator 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}); }; } Get the provider to be decorated Save reference to the original $get method Wrap the original $get method inside a new one. • Use decorator to add functionality to the existing services. Useful in cases when new functionality has to be added into core AngularJS services without touching the source.
  • 17. What exactly leads to circular dependency exception. • Suppose we have the following code: window.mainApp = angular.module("mainApp", []); mainApp.run(["mainLogger", function (mainLogger) { mainLogger.log(); }]); mainApp.service("mainLogger", [" secondaryLogger", function (secondaryLogger) { this.log = function() { console.log(); }; }]); mainApp.service("secondaryLogger", ["mainLogger", function (mainLogger) { this.log = function () { console.log(); }; }]); Both services here are dependent on each other.
  • 18. When a new service (mainLogger) is registered, its name is first inserted as a key into instanceCache with the value pointing to the INSTANTIATING token. No actual provider object is yet created. AngularJS then proceeds to creating mainLoggerProvider object: registers it in the providerCache. The framework detects that the service has a dependency on secondaryLogger service. To resolve this dependency it needs to create a secondaryLoggerProvider object, register it in the providerCache, and call its $get method in order to create an instance of the secondaryLogger service (to inject into mainLoggerProvider). At this point the framework sees the dependency on mainLoggerProvider and honestly tries to get it from the instanceCache or to instantiate it. As we remember it is already in the instanceCache dictionary still pointing to the INSTANTIATING token. Exception follows…