SlideShare a Scribd company logo
ngMess: 
Angular JS DI
Presenter 
Dmitry Ivashutin 
Software Engineer
Dependency Injection 
High-level modules should not depend on 
low-level modules. Both should depend 
on abstractions. 
 Abstractions should not depend on details. 
Details should depend on abstractions.
DI in a Nutshell 
 create the dependency 
 look up the dependency 
 have the dependency injected
The provider
Wiki: The provider 
The $provide service is responsible for telling Angular how 
to create new injectable things; these things are 
called services. Services are defined by things 
called providers, which is what you're creating when you 
use $provide. Defining a provider is done via 
the provider method on the $provide service, and you can 
get hold of the $provide service by asking for it to be injected 
into an application's config function. 
https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection
ngMess: AngularJS Dependency Injection
How do we usually inject? 
myApp.service('alerter', function () { 
http://jsfiddle.net/ae87/9x7Aq/2/ 
this.sayHello = function(){ 
alert('Hello! '); 
} 
this.sayGoodbye = function(){ 
alert('Goodbye!'); 
} 
});
Let’s start from
Create provider at configure stage 
app.config(function ($provide) { 
$provide.provider('greeting', function () { 
this.$get = function () { 
return function (name) { 
alert('Hello, ' + name); 
}; 
}; 
}); 
});
It’s a valid way
ngMess: AngularJS Dependency Injection
There are other ways
So called “services” 
Factory Service 
Provider 
Value Constant
Calling exact the same code inside 
that we wrote above
Provider way 
function provider(name, provider_) { 
assertNotHasOwnProperty(name, 'service'); 
if (isFunction(provider_) || isArray(provider_)) { 
provider_ 
= providerInjector.instantiate(provider_); 
} 
if (!provider_.$get) 
return providerCache[name + providerSuffix] 
= provider_; 
}
Factory way 
function factory(name, factoryFn) { 
return provider( 
name, 
{ 
$get: factoryFn 
}); 
}
Service way 
function service(name, constructor) { 
return factory( 
name, 
[ 
'$injector', 
function ($injector) { 
return $injector.instantiate(constructor); 
} 
]); 
}
Value way 
function value(name, val) { 
return factory( 
name, 
valueFn(val) 
); 
} 
function valueFn(value) { 
return function () { 
return value; 
}; 
}
Constant way 
function constant(name, value) { 
assertNotHasOwnProperty(name, 'constant'); 
providerCache[name] = value; 
instanceCache[name] = value; 
}
ngMess: AngularJS Dependency Injection
Syntactic sugar
Looks annoying, right? 
app.config(function($provide) { ... })
Module level access 
$provide 
.provider('greeting', ...); 
angular 
.module('myModule', []) 
.provider('greeting', ...);
“A Sound of Thunder”
ngMess: AngularJS Dependency Injection
Service Recipe 
 Utility functions via public API 
 Non-new-able stuff 
Works better for objects of custom type 
service(class) 
– registers a constructor function, 
class that will be wrapped in 
a service provider object
Factory Recipe 
 Exposing public API 
 Constructors via new-able functions 
Can produce JavaScript primitives and functions 
factory(fn) 
– registers a service factory 
function, that will be wrapped 
in a service provider object
Provider Recipe 
 Configurable stuff 
You don't need it unless you are building a 
reusable piece of code that needs global 
configuration 
provider(provider) 
– registers a service provider 
with the $injector
Value Recipe 
 Exposing static values and constants 
value(obj) 
– registers a value/object that 
can only be accessed by 
services, not providers
Constant Recipe 
 Exposing compile time static values and 
constants 
constant(obj) 
– registers a value/object 
that can be accessed by 
providers and services
Decorator
Decorator way 
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 }); 
}; 
}
Know-how 
app.config(function ($provide) { 
$provide.decorator('$log', function ($delegate) { 
// save the original function 
var _log = $delegate.log; 
// replace the original behavior 
$delegate.log = function (msg) { 
_log(msg); 
alert(msg); 
}; 
return $delegate; 
}); 
}); 
http://plnkr.co/edit/imqmvUfk4oWWuwg75sP1?p=preview
ngMess: AngularJS Dependency Injection
Few more quick facts
Injector: Why 
 Feel the power of DI 
 Control the injection real-time 
 Access DI container from outside of your app 
 Primary usage - testing
Injector: How 
function MyController($scope, $injector) { 
$scope.doSomething = function(someServiceName) { 
// someService contains the name of a service 
var service = $injector.get(someServiceName); 
service.do(); 
}; 
}
Scripts require proper order
The End! Questions?

More Related Content

ngMess: AngularJS Dependency Injection

  • 2. Presenter Dmitry Ivashutin Software Engineer
  • 3. Dependency Injection High-level modules should not depend on low-level modules. Both should depend on abstractions.  Abstractions should not depend on details. Details should depend on abstractions.
  • 4. DI in a Nutshell  create the dependency  look up the dependency  have the dependency injected
  • 6. Wiki: The provider The $provide service is responsible for telling Angular how to create new injectable things; these things are called services. Services are defined by things called providers, which is what you're creating when you use $provide. Defining a provider is done via the provider method on the $provide service, and you can get hold of the $provide service by asking for it to be injected into an application's config function. https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection
  • 8. How do we usually inject? myApp.service('alerter', function () { http://jsfiddle.net/ae87/9x7Aq/2/ this.sayHello = function(){ alert('Hello! '); } this.sayGoodbye = function(){ alert('Goodbye!'); } });
  • 10. Create provider at configure stage app.config(function ($provide) { $provide.provider('greeting', function () { this.$get = function () { return function (name) { alert('Hello, ' + name); }; }; }); });
  • 14. So called “services” Factory Service Provider Value Constant
  • 15. Calling exact the same code inside that we wrote above
  • 16. Provider way function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) return providerCache[name + providerSuffix] = provider_; }
  • 17. Factory way function factory(name, factoryFn) { return provider( name, { $get: factoryFn }); }
  • 18. Service way function service(name, constructor) { return factory( name, [ '$injector', function ($injector) { return $injector.instantiate(constructor); } ]); }
  • 19. Value way function value(name, val) { return factory( name, valueFn(val) ); } function valueFn(value) { return function () { return value; }; }
  • 20. Constant way function constant(name, value) { assertNotHasOwnProperty(name, 'constant'); providerCache[name] = value; instanceCache[name] = value; }
  • 23. Looks annoying, right? app.config(function($provide) { ... })
  • 24. Module level access $provide .provider('greeting', ...); angular .module('myModule', []) .provider('greeting', ...);
  • 25. “A Sound of Thunder”
  • 27. Service Recipe  Utility functions via public API  Non-new-able stuff Works better for objects of custom type service(class) – registers a constructor function, class that will be wrapped in a service provider object
  • 28. Factory Recipe  Exposing public API  Constructors via new-able functions Can produce JavaScript primitives and functions factory(fn) – registers a service factory function, that will be wrapped in a service provider object
  • 29. Provider Recipe  Configurable stuff You don't need it unless you are building a reusable piece of code that needs global configuration provider(provider) – registers a service provider with the $injector
  • 30. Value Recipe  Exposing static values and constants value(obj) – registers a value/object that can only be accessed by services, not providers
  • 31. Constant Recipe  Exposing compile time static values and constants constant(obj) – registers a value/object that can be accessed by providers and services
  • 33. Decorator way 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 }); }; }
  • 34. Know-how app.config(function ($provide) { $provide.decorator('$log', function ($delegate) { // save the original function var _log = $delegate.log; // replace the original behavior $delegate.log = function (msg) { _log(msg); alert(msg); }; return $delegate; }); }); http://plnkr.co/edit/imqmvUfk4oWWuwg75sP1?p=preview
  • 36. Few more quick facts
  • 37. Injector: Why  Feel the power of DI  Control the injection real-time  Access DI container from outside of your app  Primary usage - testing
  • 38. Injector: How function MyController($scope, $injector) { $scope.doSomething = function(someServiceName) { // someService contains the name of a service var service = $injector.get(someServiceName); service.do(); }; }