angularjs - services

56
service-side development

Upload: nir-kaufman

Post on 02-Dec-2014

601 views

Category:

Technology


3 download

DESCRIPTION

A presentation made for the AngularJS-IL meetup group that took place in oct 2014 at Google TLV Campus (http://www.meetup.com/AngularJS-IL/events/207559572/) its an overview of how to use services in your app. this slideshow contain a link for a reference code on github. (link in the last slide)

TRANSCRIPT

Page 1: AngularJS - Services

service-side development

Page 2: AngularJS - Services

quick introduction

Page 3: AngularJS - Services

Nir Kaufman

Head of AngularJS development department @

[email protected]

Page 4: AngularJS - Services

services - definition dependency injection services types common patterns

We will cover:

Page 5: AngularJS - Services

all examples and reference code are written in ES6

Page 6: AngularJS - Services

Services defined

Page 7: AngularJS - Services

the term ‘services’ refers to injectable objects

whose API is defined by the developer (not the framework)

Page 8: AngularJS - Services

services contain reusable business logic independent of views

Page 9: AngularJS - Services

each service starts as a plain javaScript!

object, function or primitive

Page 10: AngularJS - Services

we use one of the module methods to register!

our code as a service

Page 11: AngularJS - Services

now we can inject it into other angular components like controllers, directives & services

Page 12: AngularJS - Services

Dependency Injection

Page 13: AngularJS - Services

let’s take a high level overview of dependency injection

in angular!

Page 14: AngularJS - Services

the key players are the provide & injector!

services

Page 15: AngularJS - Services

we register our code on the injector with the provide service

https://docs.angularjs.org/api/auto/service/$provide

Page 16: AngularJS - Services

we need to provide a key as the first argument

Page 17: AngularJS - Services

the injector keeps our code in an internal object called

providerCache

angular source code, line 3926

Page 18: AngularJS - Services

we use the injector retrieve object instances

https://docs.angularjs.org/api/auto/service/$injector

Page 19: AngularJS - Services

the first time we inject a service, the injector evaluates the code and

stores the result in an instanceCach object

Page 20: AngularJS - Services

the next time that we inject the same service, the injector will first

look in the instanceCache

angular source code, line 3940

Page 21: AngularJS - Services

that’s why our services are singletons

Page 22: AngularJS - Services

we can’t use a service in the module config phase because the instanceCache

is empty until the service is injected for the first

time

Page 23: AngularJS - Services

registering services

Page 24: AngularJS - Services

We don’t need to use the provider directly. The module exposes

the necessary methods.

https://docs.angularjs.org/api/ng/type/angular.Module

Page 25: AngularJS - Services

the module exposes 5 methods used to instruct the injector how to

evaluate our code

Page 26: AngularJS - Services

.provider!an object with a $get method.

Page 27: AngularJS - Services

module.providerConstruction function for creating new instance of the service.

class Logger { ! constructor() { ! let logToConsole = false; ! this.enableConsole = function (flag) { logToConsole = flag; }; ! this.$get = function() { return { debug: function (msg) { if (logToConsole) { console.log(msg) } } } } } }

Page 28: AngularJS - Services

module.provideruse it if you need to config your service before it’s instantiatedclass Logger { ! constructor() { ! let logToConsole = false; ! this.enableConsole = function (flag) { logToConsole = flag; }; ! this.$get = function() { return { debug: function (msg) { if (logToConsole) { console.log(msg) } } } } } }

angular.module('app', []) ! .provider(‘logger’, Logger) .config(function(loggerProvider){ loggerProvider.enableConsole(false); }) ! .run(function(logger){ logger.debug(‘log message'); });

we need to call our service with a ‘Provider’ suffix when injecting into config function.

Page 29: AngularJS - Services

.service!plain javaScript Object

Page 30: AngularJS - Services

module.servicea constructor function that will be instantiated.

class Logger { ! constructor() { this.enableConsole = true; } ! debug(msg) { if (this.enableConsole) { console.log(msg) } } }

Page 31: AngularJS - Services

module.serviceuse if your object does not need to be configured.

class Logger { ! constructor() { this.enableConsole = true; } ! debug(msg) { if (this.enableConsole) { console.log(msg) } } }

angular.module('app', []) ! .service(‘logger’, Logger) ! .run(function(logger){ logger.debug(‘log message'); });

Page 32: AngularJS - Services

.factory!just a plain function

Page 33: AngularJS - Services

module.factoryFunction for creating new instance of an Object.

function logger() { ! return { ! debug: function (msg) { console.log(msg); } } } !!!function logger() { ! return function (flag) { return function (msg) { if (flag) console.log(msg); } } } !!

Page 34: AngularJS - Services

module.factoryif you want to return something other than an Object instancefunction logger() { ! return { debug: function (msg) { console.log(msg); } } } !!function logger() { ! return function (flag) { return function (msg) { if (flag) console.log(msg); } } } !!

angular.module('app', []) .factory(‘logger’, logger) .run(function(logger){ logger.debug(‘log message'); });

angular.module('app', []) ! .factory(‘logger’, logger) .run(function(logger){ logger(true)(‘log message'); });

Page 35: AngularJS - Services

.value!a value of any type

Page 36: AngularJS - Services

module.valueService instance object. registered “as-is”.

function randomise() { return Math.random() * 10; } !var id = 52334556; !var product = {id: 52345, inStock: true}; !!class User { ! constructor(name) { this.firstName = name; } }

Page 37: AngularJS - Services

module.valueuse it when you need a simple object or primitive.

function randomise() { return Math.random() * 10; } !!!!!!!!class User { ! constructor(name) { this.firstName = name; } }

angular.module('app', []) ! .value(‘randomise’, randomise) ! .run(function(randomise){ var num = randomise() });

angular.module('app', []) ! .value(‘User’, User) ! .run(function(user){ var joe = new User(‘joe’) });

Page 38: AngularJS - Services

.constant!a value of any type

Page 39: AngularJS - Services

module.constantConstant value. registered on the injector instanceCache.

var SERVERS = { DEVELOPMENT : "http://localhost:8080/app", DEBUGGING : "http://localhost:5789", PRODUCTION : "http://application.com" };

angular.module('app', []) .constant('SERVERS', SERVERS) ! .config(function (SERVERS) { console.log(SERVERS.PRODUCTION); }) ! .run(function (SERVERS) { console.log(SERVERS.DEVELOPMENT); });

because constants are registered on the injector instanceCache, they can be injected into the config function.

Page 40: AngularJS - Services

service and factory are shorthands for providersclass Logger { ! constructor() { ! let logToConsole = false; ! this.enableConsole = function (flag) { logToConsole = flag; }; ! this.$get = ! function () { return { debug: function (msg) { if (logToConsole) { console.log(msg) } } } } } }

ProviderFactoryService

Page 41: AngularJS - Services

common patterns

Page 42: AngularJS - Services

Problem:!I want to decide which service to

inject dynamically.

Page 43: AngularJS - Services

Solution:!use the $injector service to grab an instance of the service you need.

Page 44: AngularJS - Services

show me some code!

class Logger { ! constructor($injector) { this.injector = $injector; } ! debug(msg, useLogService) { useLogService ? this.injector.get('$log').debug(msg) : console.log(msg); } }

angular.module('app', []) ! .service('logger', ['$injector', Logger]) ! .run(function (logger) { logger.debug('something to debug', true) });

dynamic-inject.js

Page 45: AngularJS - Services

Problem:!I want to be able to extend an

existing service.

Page 46: AngularJS - Services

Solution:!Services are plain javaScript

objects. Prototypal inheritance works as usual.

Page 47: AngularJS - Services

show me some code!class ItemList { ! constructor() { this.items = []; } ! addItem(item) { this.items.push(item); } ! removeItem(item){ this.items.splice(this.items.indexOf(item), 1); } } !!class TaskList extends ItemList { ! constructor() { super() } ! getItems () { return this.items; } }

prototype-inheritance.js

angular.module('app', []) ! .service('taskList', TaskList) ! .run(function (taskList) { taskList.addItem("some item to be added"); console.log(taskList.getItems()); });

Page 48: AngularJS - Services

Problem:!I want to be able to extend core angular or 3rd party services.

Page 49: AngularJS - Services

Solution:!use the $decorator method to extend or override services.

Page 50: AngularJS - Services

show me some code!function logDecorator($delegate) { ! $delegate.debug = function (msg) { let time = new Date().getTime(); console.log(time + " : " + msg); }; ! return $delegate } !export default logDecorator;

decorator.js

angular.module('app', []) ! .config(['$provide', function ($provide) { $provide.decorator('$log', logDecorator) }]) ! .run(['$log', function ($log){ $log.debug('logging with timestamp!'); }]);

Page 51: AngularJS - Services

Problem:!I want to register new services at

runtime (lazy register)

Page 52: AngularJS - Services

Solution:!get a reference to the $provide service and use it outside the

config block

Page 53: AngularJS - Services

show me some code!class Product { ! constructor(type) { this.productType = type; } ! getType () { return this.productType; } } !class ProductFactory { ! constructor($provider) { ! let provider = $provider; ! this.$get = function () { return { registerProduct : function (type) { provider.value(type, new Product(type)); } } } } } product-factory.js

Page 54: AngularJS - Services

show me some code!angular.module('app', []) ! .provider('productFactory', ['$provide',ProductFactory]) ! .run(function($injector, productFactory) { ! productFactory.registerProduct(‘chair'); ! var theChair = $injector.get(‘chair'); ! console.log(theChair.getType()); });

product-factory.js

Page 55: AngularJS - Services

grab the code

https://github.com/nirkaufman/angularjs-services

Page 56: AngularJS - Services

Thank you.