angularjs - services

Post on 02-Dec-2014

601 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

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

service-side development

quick introduction

Nir Kaufman

Head of AngularJS development department @

Nir@500tech.com

services - definition dependency injection services types common patterns

We will cover:

all examples and reference code are written in ES6

Services defined

the term ‘services’ refers to injectable objects

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

services contain reusable business logic independent of views

each service starts as a plain javaScript!

object, function or primitive

we use one of the module methods to register!

our code as a service

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

Dependency Injection

let’s take a high level overview of dependency injection

in angular!

the key players are the provide & injector!

services

we register our code on the injector with the provide service

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

we need to provide a key as the first argument

the injector keeps our code in an internal object called

providerCache

angular source code, line 3926

we use the injector retrieve object instances

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

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

stores the result in an instanceCach object

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

look in the instanceCache

angular source code, line 3940

that’s why our services are singletons

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

registering 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

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

evaluate our code

.provider!an object with a $get method.

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

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.

.service!plain javaScript Object

module.servicea constructor function that will be instantiated.

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

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

.factory!just a plain function

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

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

.value!a value of any type

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

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

.constant!a value of any type

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.

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

common patterns

Problem:!I want to decide which service to

inject dynamically.

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

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

Problem:!I want to be able to extend an

existing service.

Solution:!Services are plain javaScript

objects. Prototypal inheritance works as usual.

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

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

Solution:!use the $decorator method to extend or override 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!'); }]);

Problem:!I want to register new services at

runtime (lazy register)

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

config block

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

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

grab the code

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

Thank you.

top related