ngMess: AngularJS Dependency Injection
- 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);
};
};
});
});
- 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_;
}
- 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;
}
- 24. Module level access
$provide
.provider('greeting', ...);
angular
.module('myModule', [])
.provider('greeting', ...);
- 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
- 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();
};
}