ngMess: AngularJS Dependency Injection

40
ngMess: Angular JS DI

description

TechTalk on iTechart Hackathon'2014 "ngMess: AngularJS Dependency Injection" - getting a little bit deeper into working with angular services, discussing difference between providers/factories/services/values/constants and reviewing its' source codes. Plus some general advice and use cases for using each type of injectable objects.

Transcript of ngMess: AngularJS Dependency Injection

Page 1: ngMess: AngularJS Dependency Injection

ngMess: Angular JS DI

Page 2: ngMess: AngularJS Dependency Injection

Presenter

Dmitry Ivashutin Software Engineer

Page 3: ngMess: AngularJS Dependency Injection

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.

Page 4: ngMess: AngularJS Dependency Injection

DI in a Nutshell

create the dependency

look up the dependency

have the dependency injected

Page 5: ngMess: AngularJS Dependency Injection

The provider

Page 6: ngMess: AngularJS Dependency Injection

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

Page 7: ngMess: AngularJS Dependency Injection
Page 8: ngMess: AngularJS 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!');

} });

Page 9: ngMess: AngularJS Dependency Injection

Let’s start from

Page 10: ngMess: AngularJS Dependency Injection

Create provider at configure stage

app.config(function ($provide) {

$provide.provider('greeting', function () {

this.$get = function () {

return function (name) {

alert('Hello, ' + name);

};

};

});

});

Page 11: ngMess: AngularJS Dependency Injection

It’s a valid way

Page 12: ngMess: AngularJS Dependency Injection
Page 13: ngMess: AngularJS Dependency Injection

There are other ways

Page 14: ngMess: AngularJS Dependency Injection

So called “services”

Factory Service

Value Constant

Provider

Page 15: ngMess: AngularJS Dependency Injection

Calling exact the same code inside that we wrote above

Page 16: ngMess: AngularJS Dependency Injection

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_; }

Page 17: ngMess: AngularJS Dependency Injection

Factory way

function factory(name, factoryFn) { return provider( name,

{ $get: factoryFn }); }

Page 18: ngMess: AngularJS Dependency Injection

Service way

function service(name, constructor) {

return factory( name, [

'$injector', function ($injector) {

return $injector.instantiate(constructor); } ]); }

Page 19: ngMess: AngularJS Dependency Injection

Value way

function value(name, val) {

return factory( name,

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

Page 20: ngMess: AngularJS Dependency Injection

Constant way

function constant(name, value) { assertNotHasOwnProperty(name, 'constant');

providerCache[name] = value; instanceCache[name] = value; }

Page 21: ngMess: AngularJS Dependency Injection
Page 22: ngMess: AngularJS Dependency Injection

Syntactic sugar

Page 23: ngMess: AngularJS Dependency Injection

Looks annoying, right?

app.config(function($provide) { ... })

Page 24: ngMess: AngularJS Dependency Injection

Module level access

angular .module('myModule', [])

.provider('greeting', ...);

$provide

.provider('greeting', ...);

Page 25: ngMess: AngularJS Dependency Injection

“A Sound of Thunder”

Page 26: ngMess: AngularJS Dependency Injection
Page 27: 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

Page 28: ngMess: AngularJS Dependency Injection

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

Page 29: ngMess: AngularJS Dependency Injection

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

Page 30: ngMess: AngularJS Dependency Injection

Value Recipe

Exposing static values and constants

value(obj)

– registers a value/object that

can only be accessed by

services, not providers

Page 31: ngMess: AngularJS Dependency Injection

Constant Recipe

Exposing compile time static values and constants

constant(obj)

– registers a value/object

that can be accessed by

providers and services

Page 32: ngMess: AngularJS Dependency Injection

Decorator

Page 33: ngMess: AngularJS Dependency Injection

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 }); }; }

Page 34: ngMess: AngularJS Dependency Injection

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

Page 35: ngMess: AngularJS Dependency Injection
Page 36: ngMess: AngularJS Dependency Injection

Few more quick facts

Page 37: ngMess: AngularJS Dependency Injection

Injector: Why

Feel the power of DI

Control the injection real-time

Access DI container from outside of your app

Primary usage - testing

Page 38: ngMess: AngularJS Dependency Injection

Injector: How

function MyController($scope, $injector) { $scope.doSomething = function(someServiceName) { // someService contains the name of a service

var service = $injector.get(someServiceName); service.do(); }; }

Page 39: ngMess: AngularJS Dependency Injection

Scripts require proper order

Page 40: ngMess: AngularJS Dependency Injection

The End! Questions?