Davide Pegoraro
Services I services forniscono un metodo per gestire i dati nell’intero ciclo di vita dell'applicazione e permettono di comunicare attraverso i controller in modo coerente Dal punto di vista sintattico, un Services restituisce un oggetto singleton che rimane in vita fino alla chiusura del browser. Questo significa che si ha la necessità di definire un Service se si desidera che l’oggetto venga creato una sola volta e alle successive richieste venga semplicemente restituita l’istanza creata. Il Services può avere delle dipendenze e l’elemento che produce è iniettabile.
Services Esistono 5 modi diversi per creare un service factory service provider constant value
Services factory E’ il metodo più comune e semplice Qui una semplice definizione Namespace dei servizi angular.module('MyApp.services', []) .factory('anagraficaService', function ($http) { var getAll = function () { return $http({ method: 'GET', url: globalHostName + "/api/Anagrafica" }); }; return { GetAll: function () { return getAll(); } })
Services factory var controllers = angular.module('MyApp.controllers', ['MyApp.services']); controllers.controller('CtrlServices', function ($scope, anagraficaService) { anagraficaService.GetAll() .success(function (data, status, headers, config) { $scope.list = data; }) .error(function (data, status, headers, config) { }); Factory iniettata a runtime Da notare che il ‘success’ è gestito non all’interno del service, ma nel controller In quanto la chiamata è asincrona
Services LOADING DEI MODULE var myapp = angular.module('MyApp', ['ngRoute', 'MyApp.filters', 'MyApp.services', 'MyApp.directives', 'MyApp.controllers']); myapp.run(function ($rootScope) { console.log("Eseguito alla prima esecuzione") }); E’ quanto di più vicino ad una funzione main
Services SERVICE Utilizzato quando si ha la necessità di usare una modalità a ‘costruttore’ var Person = function($http) { this.getName = function() { return $http({ method: 'GET', url: '/api/user' }); }; angular.service('personService', Person);
Services provider Il provider è definito come un tipo custom che implementa il metodo $get. Il provider è configurabile in fase di configurazione. Questo metodo non è altro che una funzione Factory. angular.module('myApp') .factory('myService', function() { return { 'username': 'auser' } }) // Equivalente .provider('myService', { $get: function() { });
Services provider Ma perchè usare un provider? Il motivo sta nel fatto che un provider rispetto ad un normale service può essere configurato esternamente tramite config() angular.module('myApp', []) .config(function(githubServiceProvider) { githubServiceProvider.setGithubUrl("git@github.com"); }); angular.module('myApp', []) .provider('UserService', { favoriteColor: null, setFavoriteColor: function(newColor) { this.favoriteColor = newColor; }, $get: function($http) { return { 'name': 'Ari', getFavoriteColor: function() { return this.favoriteColor || 'unknown'; …
Services consTANT E’ possibile registrare un valore su un modulo principale ed iniettare la relativa dipendenza a servizio angular.module('myApp') .constant('apiKey', '123123123') .controller('MyController', function($scope, apiKey) { $scope.apiKey = apiKey; })
Services VALUE Il comportamento è molto simile alle costant angular.module('myApp') .value('apiKey', '123123123') .controller('MyController', function($scope, apiKey) { $scope.apiKey = apiKey; })
Services constant/VALUE Il comportamento è molto simile per entrambi, ma la differenze sostanziale è che una costant può essere iniettata in un config, un value no. angular.module('myApp', []) .constant('apiKey', '123123123') .config(function(apiKey) { // apikey è risolta }) .value('FBid', '231231231') .config(function(FBid) { // Errore Fbid è sconosciuta!!! });
PROMISE Una delle caratteristiche interessanti e largamente utilizzate di JavaScript è il supporto alla programmazione asincrona, cioè la possibilità di eseguire attività in background che non interferiscono con il flusso di elaborazione principale. I due principali elementi che consentono di sfruttare il modello di programmazione asincrono in JavaScript sono gli eventi e le callback.
PROMISE Il classico esempio di utilizzo delle callback è quello delle chiamate Ajax, come quello mostrato dal seguente codice: $.get("/users", { id: "12345" }, function(user) { $("#resultMessage").html("Nome utente: " + user.Name); } );
PROMISE Utilizzare le callback, quindi, può essere abbastanza intuitivo in situazioni relativamente semplici, ma può risultare complesso all'aumentare della complessità del codice Tra i principali difetti dell’uso intensivo delle callback segnaliamo: -una scarsa leggibilità del codice -difficoltà di composizione delle callback e di sincronizzazione del flusso di elaborazione -difficoltà di gestione degli errori e di debug, soprattutto in presenza di callback anonime.
PROMISE Ad aiutarci vengono in soccorso le 'promise‘, che rappresentano una promessa che un risultato verrà fornito non appena disponibile. Una promise può trovarsi in questi stadi: pending è lo stato in cui non è stato ancora ottenuto il risultato della chiamata asincrona resolved in questo stato la chiamata asincrona ha prodotto un risultato rejected rappresenta la situazione in cui non è possibile ottenere un risultato dalla chiamata asincrona, tipicamente per il verificarsi di una condizione d’errore
PROMISE Il vantaggio dell’utilizzo delle promise rispetto alle callback consiste nel rendere il codice più leggibile, più simile al flusso di esecuzione sincrona e in alcune situazioni anche più efficiente. Diversi linguaggi di programmazione supportano il meccanismo delle promise per la gestione della programmazione asincrona. Alcuni in maniera nativa, altri ricorrendo a librerie esterne. Allo stato attuale JavaScript non supporta nativamente le promise, anche se c’è una proposta di inclusione tra le specifiche di ECMAScript 6, pertanto dobbiamo ricorrere a librerie esterne come ad esempio Q. https://github.com/kriskowal/q
PROMISE Un piccolo esempio var getUser = function() { var deferred = Q.defer(); $.get("/users", [id: "12345"], deferred.resolve); return deferred.promise; } getUser().then(function(user) { $("#resultMessage").html("Nome utente: " + user.Name); });
PROMISE Un piccolo esempio con Angular .factory('promiseService', function ($q, $http) { var getAllData = function () { var deferred = $q.defer(); $http.get(globalHostName + "/api/Anagrafica") .success(function (data) { deferred.resolve(data); }) .error(function (reason) { deferred.reject(reason); }); return deferred.promise; }; return { GetAllData: function () { return getAllData(); }
PROMISE Un piccolo esempio con Angular .controller('CtrlPromise', function ($scope, promiseService) { promiseService.GetAllData().then(function (data) { $scope.list3 = data; }, function (err) { });
PROMISE Un esempio con Angular e notiche .factory('GithubService', function($q, $http) { var getEventsFromRepo = function() { // task } var service = { makeMultipleRequests: function(repos) { var d = $q.defer(),percentComplete = 0,output = []; try{ for (var i = 0; i < repos.length; i++) { output.push(getEventsFromRepo(repos[i])); percentComplete = (i+1)/repos.length * 100; d.notify(percentComplete); d.resolve(output); return d.promise; }catch(error){ d.reject(error) return service; });
PROMISE Un esempio con Angular e notiche .controller('HomeController', function($scope, GithubService) { GithubService.makeMultipleRequests(['auser/beehive', 'angular/angular.js']) .then(function(result) { // Valutazione risultato }, function(err) { // Gestione errore }, function(percentComplete) { $scope.progress = percentComplete; });