Post on 02-Jul-2015
description
ngMess: Angular JS DI
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
How do we usually inject?
http://jsfiddle.net/ae87/9x7Aq/2/
myApp.service('alerter', function () {
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
There are other ways
So called “services”
Factory Service
Value Constant
Provider
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; }
Syntactic sugar
Looks annoying, right?
app.config(function($provide) { ... })
Module level access
angular .module('myModule', [])
.provider('greeting', ...);
$provide
.provider('greeting', ...);
“A Sound of Thunder”
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
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?