AngularJS - Services
Post on 02-Dec-2014
599 Views
Preview:
DESCRIPTION
Transcript
service-side development
quick introduction
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