Introduzione alle Single Page Application



Documenti analoghi
Capitolo 4 Pianificazione e Sviluppo di Web Part

Registratori di Cassa

IL MIO PRIMO SITO: NEWS

Esercizio data base "Biblioteca"

OSSIF WEB. Manuale query builder

NOVITÀ SITI COMMERCIALISTA

Manuale Operativo per l utilizzo della piattaforma E-Learning@AQ. Versione 1.1

Corso su LINQ Lezione 16. Introduzione

GHPPEditor è un software realizzato per produrre in modo rapido e guidato un part program per controlli numerici Heidenhain.

LA GESTIONE DELLE VISITE CLIENTI VIA WEB

Il CMS Moka. Giovanni Ciardi Regione Emilia Romagna

LE CARATTERISTICHE DEI PRODOTTI MULTIVARIANTE

Soluzione dell esercizio del 2 Febbraio 2004

ADDING SOCIAL PLUGINS TO YOUR OWN SITE

A tal fine il presente documento si compone di tre distinte sezioni:

1) GESTIONE DELLE POSTAZIONI REMOTE

Il web server Apache Lezione n. 3. Introduzione

Il calendario di Windows Vista

ICARO Terminal Server per Aprile

Regione Toscana. ARPA Fonte Dati. Manuale Amministratore. L. Folchi (TAI) Redatto da

. A primi passi con microsoft a.ccepss SommarIo: i S 1. aprire e chiudere microsoft access Start (o avvio) l i b tutti i pro- grammi

A tal fine il presente documento si compone di tre distinte sezioni:

Il sistema C.R.M. / E.R.M.

Editing e gestione delle views per il modulo Landing Page Espositore

Corso Drupal «Project management»

I database relazionali sono il tipo di database attualmente piu diffuso. I motivi di questo successo sono fondamentalmente due:

NAVIGAZIONE DEL SI-ERC: UTENTE PROGETTISTA

Guida alla registrazione on-line di un DataLogger

19. LA PROGRAMMAZIONE LATO SERVER

Figura 1 Le Icone dei file di Excel con e senza macro.

GUIDA UTENTE PRIMA NOTA SEMPLICE

MANUALE D USO DELLA PIATTAFORMA ITCMS

LABORATORIO PER IL DESIGN DELLE INTERFACCE PEGORARO ALESSANDRO CASSERO.IT MANUALE DI AGGIORNAMENTO, MANUTENZIONE E USO DEL SITO

Database e reti. Piero Gallo Pasquale Sirsi

Università Politecnica delle Marche. Progetto Didattico

Banca dati Professioniste in rete per le P.A. Guida all uso per le Professioniste

Mac Application Manager 1.3 (SOLO PER TIGER)

Esercizi di JavaScript

NOTE OPERATIVE. Prodotto Inaz Download Manager. Release 1.3.0

ATOLLO BACKUP GUIDA INSTALLAZIONE E CONFIGURAZIONE

Progettazione : Design Pattern Creazionali

MANUALE UTENTE Fiscali Free

Manuale servizio Webmail. Introduzione alle Webmail...2 Webmail classica (SquirrelMail)...3 Webmail nuova (RoundCube)...8

Manuale Servizio NEWSLETTER

Breve introduzione curata da Alessandro Benedetti. Struts2-Introduzione e breve guida

Implementazione di MVC. Gabriele Pellegrinetti

Visual basic base Lezione 01. L'ambiente di sviluppo

INVIO SMS

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

Che cos'è un modulo? pulsanti di opzione caselle di controllo caselle di riepilogo

EXPLOit Content Management Data Base per documenti SGML/XML

HBase Data Model. in più : le colonne sono raccolte in gruppi di colonne detti Column Family; Cosa cambia dunque?

SWIM v2 Design Document

Lande Immortali: Riepilogo dello Stato di Avanzamento del Progetto

L amministratore di dominio

File, Modifica, Visualizza, Strumenti, Messaggio

Overview su Online Certificate Status Protocol (OCSP)

Progetto: ARPA Fonte Dati. ARPA Fonte Dati. Regione Toscana. Manuale Amministratore

FtpZone Guida all uso

Port Community System del Porto di Ravenna CONFIGURAZIONE

Guida all uso di Java Diagrammi ER

Progetto ittorario Anno scol

Settaggio impostazioni tema. Cliccando nuovamente su aspetto e poi su personalizza si avrà modo di configurare la struttura dinamica della template.

Soluzione dell esercizio del 12 Febbraio 2004

Corso di PHP. Prerequisiti. 6.1 PHP e il web 1. Conoscenza HTML Tecnica della programmazione Principi di programmazione web

File Server Resource Manager (FSRM)

SOMMARIO... 3 INTRODUZIONE...

Progetto Eleven. Introduzione. Componenti del gruppo. Gruppo 11

Guida all uso delle Web View su ios

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

FPf per Windows 3.1. Guida all uso

CP Customer Portal. Sistema di gestione ticket unificato

ELENCO CLIENTI FORNITORI Patch1

Database 1 biblioteca universitaria. Testo del quesito

Come modificare la propria Home Page e gli elementi correlati

Invio SMS. DM Board ICS Invio SMS

MAUALE PIATTAFORMA MOODLE

MANUALE ESSE3 Gestione Registro delle lezioni

Uso dei modelli/template

Definizione Parte del software che gestisce I programmi applicativi L interfaccia tra il calcolatore e i programmi applicativi Le funzionalità di base

PROGRAMMA GESTIONE TURNI MANUALE UTENTE. Programma Gestione Turni Manuale Utente versione 1.1

I MODULI Q.A.T. PANORAMICA. La soluzione modulare di gestione del Sistema Qualità Aziendale

MODELLO CLIENT/SERVER. Gianluca Daino Dipartimento di Ingegneria dell Informazione Università degli Studi di Siena

MAGAZZINO FISCALE (agg. alla rel )

Come creare una pagina Facebook e collegarla al sito mosajco

Presentazione Data Base

12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP)

Let's start! File > New Project > Ruby > Ruby on Rails Application (events)

RIFERIMENTI ATTORI GLOSSARIO. ERRORI COMUNI REV. REQUISITI INGEGNERIA DEL SOFTWARE Università degli Studi di Padova

ESERCITAZIONE Semplice creazione di un sito Internet

Architettura MVC-2: i JavaBeans

SITI-Reports. Progetto SITI. Manuale Utente. SITI-Reports. ABACO S.r.l.

Introduzione alla teoria dei database relazionali. Come progettare un database

USARE JOOMLA 1.7/2.5 per gestire il vostro sito.

Esempi di algoritmi. Lezione III

ammesso solo con il tuo consenso. Le modifiche apportate hanno lo scopo di semplificare il controllo di quali

Per chi ha la Virtual Machine: avviare Grass da terminale, andando su Applicazioni Accessori Terminale e scrivere grass

Estensioni e modelli. Ancora poco conosciuti, consentono di estendere la suite per l ufficio. Ecco come servirsene

Come masterizzare dischi con Nero 11

4.1 FAX Sollecito consegne via (Nuova funzione)

Transcript:

Introduzione alle Single Page Application Abstract Introduzione al mondo delle Single Page Application attraverso DurandalJS, RequireJS, BreezeJS, QJS, etc.. Alberto Acerbis for TheDiligence - 2 dicembre 2013

Sommario Cos è una SPA... 2 DurandalJS... 3 Struttura di una SPA con DurandalJS... 3 Creazione di una pagina... 4 Creazione del ViewModel... 4 Creazione della View... 6 Il Sistema di Routing... 7 BreezeJS... 9 Caratteristiche principali... 9 EntityManager... 9 Entity... 10 Data Binding... 10 Query... 11 Salvataggio dei Dati... 11 Metadata... 12 Promise Vs Callback... 13 Function Modules in RequireJS... 16 Fonti... 18

Cos è una SPA Una SPA è un'applicazione che prevede un modello di sviluppo completamente diverso dalle classiche applicazioni web. In una SPA l'applicazione è suddivisa in due layer principali con responsabilità ben precise: il client e il server. Il client ha la responsabilità di mostrare i dati all'utente e di permettere a questo di interagire con i dati stessi. Il server ha il compito di fornire le API di accesso ai dati che sono accedute dal client sia per leggere che per scrivere. Il layer client, e questa è la grande novità, è sviluppato completamente in JavaScript, HTML e CSS e quindi gira interamente sul browser. Il layer server può essere invece sviluppato utilizzando qualunque piattaforma server (Web API, ASP.NET MVC, ma anche servizi basati su Java o PHP o altro ancora). Client e server comunicano sfruttando normali richieste AJAX (in genere tramite il protocollo REST). Sviluppare una SPA da zero significa doversi occupare di diversi aspetti come il binding dei dati all interfaccia, e di questo ne abbiamo parlato al primo incontro introducendo KnockoutJS, la navigazione tra le pagine, il download dei file JavaScript e HTML necessari, la compatibilità tra i browser. Tutto questo richiede un approfondita conoscenza di JavaScript, oltre che un buon monte ore di tempo disponibile. La standardizzazione, e la continua diffusione di JavaScript, hanno fortunatamente permesso la creazione di framework che si occupano di gestire la maggior parte delle complessità infrastrutturali di un SPA lasciando a noi il compito di scrivere il codice di business. Di questi framework ne esistono ormai diversi, uno di questi, AngularJS, lo abbiamo visto nella presentazione di Gianni, oggi ci occuperemo di DurandalJS.

DurandalJS DurandalJS è un framework sviluppato dal team Caliburn.Micro, tanto per intenderci gli stessi di MVVM. La potenza di questo framework consiste nel fatto che il team non ho reinventato nulla, come cita il sito ufficiale, non hanno reinventato la ruota da zero, bensì ha riutilizzato framework già largamente diffusi sul web, come KnockoutJS, RequireJS e jquery e li ha uniti sotto un unico cappello. 1. JQuery viene sfruttato per le promise e per la manipolazione del DOM. 2. KnockoutJS per l implementazione del pattern MVVM. 3. RequireJS per la modularizzazione del codice. Di suo, DurandalJS, implementa un meccanismo di navigazione e un servizio di messaggistica, oltre che un sistema di routing che mappi gli url alle relative view, un meccanismo di popup, uno splash screen e altri aspetti più o meno secondari. Struttura di una SPA con DurandalJS Il template di DurandalJS nell ambiente di Visual Studio genera una applicazione ASP.NET MVC classica a cui aggiunge HTML, CSS e JavaScript, oltre a classi lato server e lato client. Dal punto di vista del server genera un controller, una view e una classe che genera un bundle. Il controller, con l originale nome di DurandalController, ha un solo metodo (index) che non fa altro che richiamare la view all interno della quale è ospitata la SPA. La view è estremamente semplice <body> <div id="applicationhost"> @RenderPage("_splash.cshtml") </div> @Scripts.Render("~/scripts/vendor") <script src="/app/durandal/amd/require.js" data-main="app/main"></script> </body>

Nella view è dichiarato un tag div all interno del quale verranno visualizzate le pagine dell applicazione, lo script del bundle generato dal template e infine il tag script responsabile dell avvio dell applicazione. Per quanto riguarda il bundle c è poco da aggiungere, la classe generata dal template non fa altro che prendere i file JavaScript necessari al template stesso e includerli nel bundle scripts/vendor.js che è poi quello utilizzato dalla view vista nel codice precedente. Da sottolineare che nel bundle non vi è presenza dei file JavaScript di Durandal questi infatti vengono caricati all occorrenza tramite Require.js. Vedremo in seguito l importanza di questa libreria. Molto più interessante è osservare cosa è successo lato client. I file necessari a Durandal sono inclusi un due cartelle App e Scripts. Nella cartella Scripts sono contenuti i file a cui Durandal si appoggia (RequireJS, KnockoutJS); i file JS strettamente appartenenti a Durandal si trovano in una sottocartella che prende il nome di Durandal. Questa cartella si può trovare nella cartella Scripts, nel caso del template Durandal, nella cartella App nel caso del template HotTowel, di John Papa, che è un implementazione di Durandal. Nella cartella App c è il file che viene lanciato al caricamento della SPA (main.js) e poi ci sono le View, che non sono altro che pagine HTML ridotte, con i relativi viewmodels, contenuti nella cartella ViewModels. Anche in questo caso ci sono alcune piccole differenza fra il template Durandal ed il template HotTowel, il secondo risulta avere una struttura un poco più ordinata e logica a mio avviso. Il nostro codice andrà a popolare sostanzialmente queste due cartelle. Creazione di una pagina La creazione di una pagina si articola in tre azioni 1. Creazione del ViewModel 2. Creazione della View 3. Aggiunta al sistema di routing Creazione del ViewModel Si tratta del file JavaScript contenente la logica della pagina. In esso vengono invocati i servizi per recuperare e/o modificare i dati. Il ViewModel espone anche le proprietà che compongono i dati che successivamente vengono collegati sulla View; in genere si tratta di observable o observabearray di Knockout in modo da poter sfruttare pienamente il relativo meccanismo di routing di quest ultimo.

define(['services/datacontext'], function (datacontext) { var coaches = ko.observablearray(); var activate = function () { // go get local data, if we have it return datacontext.getcoachpartials(speakers); ; var refresh = function () { return datacontext.getcoachpartials(speakers, true); ; var vm = { activate: activate, coaches: coaches, title: 'Coaches', refresh: refresh ; ); return vm; Dall esempio di codice possiamo vedere che un ViewModel non è altro che un modulo creato tramite la funzione define di RequireJS. Questa funzione accetta in input una lista di stringhe che rappresentano il riferimento a altri file JavaScript che non sono altro che moduli caricati sempre da RequireJS e sono quelli da cui il nostro ViewModel dipende. L ultimo parametro della funzione define è un callback che viene invocato quando RequireJS finisce di scaricare i file. Ad ogni parametro del callback corrisponde un istanza delle dipendenze specificate prima. Il callback deve restituire un oggetto che è quello che poi viene collegato alla View. Questo oggetto, come anticipato, può contenere sia proprietà che metodi che possono quindi essere invocati dalla View tramite la sintassi di KnockoutJS. Ci sono poi una serie di metodi opzionali che, se presenti, vengono invocati dal motore di DurandalJS, i più importanti sono 1. canactivate: invocato per specificare se la pagina può essere aperta

2. activate: invocato quando si naviga verso la pagina legata al ViewModel 3. candeactivate: invocato per specificare se si può abbandonare la pagina 4. deactivate: invocato quando si esce dalla pagina legata al ViewModel. E importante sottolineare che i metodi canactivae e candeactivate possono restituire un boolean o una promise, che a sua volta restituisce un boolean una volta risolta, mentri i metodi activate e deactivate possono o no restituire nulla, oppure una promise. Ovviamente, in accordo con i principi della programmazione asincrona, per tutti i metodi, nel caso venga restituita una promise, DurandalJS attende la risoluzione della stessa prima di proseguire nella pipeline. Fra i metodi elencati quello che praticamente è sempre presente è activate in quanto è il responsabile dei dai che vengono inizialmente visualizzati sulla View. Il file ViewModel, nel nostro caso coaches.js, dev essere salvato nella cartella ViewModels; deve perché, come vedremo, il sistema di routing di DurandalJS prevede questa disposizione dei file. Creazione della View La View è un file HTML, senza i tag di inizializzazione. Ricordiamoci che stiamo sviluppando una SPA, quindi tutta l applicazione è contenuta all interno di una singola pagina, perciò non avrebbe senso continuare a definire nuove pagine che SPA sarebbe!?!?! La View contiene il markup necessario a mostrare all utente i dati esposti dal ViewModel e si trova, fisicamente, nella cartella App/Views. L associazione tra la View ed il ViewModel viene risolta automaticamente da DurandalJS. Innanzitutto Durandal sfrutta il nome dei file per risolvere questa associazione, quindi i file che hanno lo stesso nome che si trovano nelle cartelle Views e ViewModels, vengono automaticamente associati fra loro. In seguito, grazie a KnockoutJS, Durandal associa i dati del ViewModel alla View, quindi è chiaro che noi dobbiamo rispettare la sintassi di KnockoutJS per decidere come visualizzare i nostri dati all utente <section class="view"> <header> <a class="btn btn-info btn-force-refresh pull-right" data-bind="click: refresh" href="#"><i class="icon-refresh"></i> Refresh</a> <h3 class="page-title" data-bind="text: title"></h3> <div class="article-counter"> <address data-bind="text: speakers().length"></address> <address>found</address>

</div> </header> <section class="view-list" data-bind="foreach: coaches"> <article class="article-container-full-width"> <div> <img data-bind="attr: { src: imagename " class="img-polaroid"/> <address data-bind="text: firstname"></address> <address data-bind="text: lastname"></address> </div> </article> </section> </section> Come si può vedere il codice delle View è estremamente semplice. Non abbiamo fatto altro che sfruttare Knockout per legare le proprietà del ViewMode agli oggetti della View e viceversa Le complessità ovviamente possono aumentare con l aumentare della complessità dell interfaccia, ma KnockoutJS mette a disposizione diversi meccanismi per semplificare lo sviluppo dell interfaccia, primo fra tutti il meccanismo dei custom binding dove i binding di base non siano applicabili; ovviamente l obiettivo è mantenere il codice delle interfacce il più pulito possibile. Il Sistema di Routing Di cosa stiamo parlando? Del modulo di DurandalJS che si occupa di trasformare un url in una richiesta a una specifica associazione View/ViewModels nella nostra SPA. Nel template originale la configurazione del routing è contenuta nel file shell.js, io preferisco creare un file separato, in genere config.js, dove specificare i parametri di configurazione della mia SPA. In ogni caso, al di là delle scelte personali di ognuno di noi, vediamo come si configura questo modulo var routes = [{ url: 'sessions', moduleid: 'viewmodels/sessions', name: 'Sessions', visible: true,

caption: 'Sessions', settings: { caption: '<i class="icon-book"></i> Sessions', { url: 'coaches', moduleid: 'viewmodels/coaches', name: 'Coaches', caption: 'Coaches', visible: true, settings: { caption: '<i class="icon-user"></i> Coaches', { url: 'sessiondetail/:id', moduleid: 'viewmodels/sessiondetail', name: 'Edit Session', caption: 'Edit Session', visible: false, { url: 'sessionadd', moduleid: 'viewmodels/sessionadd', name: 'Add Session', visible: false, caption: 'Add Session', settings: { admin: true, caption: '<i class="icon-plus"></i> Add Session' ];

BreezeJS Breeze è una libreria JavaScript che consente di gestire i dati nelle applicazioni Rich Client. L obiettivo principale di Breeze è quello di permettere la condivisione dei dati fra una pagina ed un altra senza necessariamente passare sempre dal server, e la navigabilità in essi, ossia fornire oggetti grafici complessi. Caratteristiche principali Creare oggetti lato client che rispecchiano il modello lato server. Breeze crea questi oggetti dinamicamente e lega le proprietà di questi oggetti alla UI della nostra applicazione (KnockuotJS nel nostro caso). In questo modo ogni oggetto di Breeze sa quando e quale dato è cambiato al suo interno. Permette la scrittura di Query in JavaScript, con tutte le fetures del caso, come ordinamento, filtro, raggruppamento, etc. Implementa OData (Open Data Protocol) in modo da poter espandere il risultato di una query con entità correlate. Permette di salvare un oggetto, o un gruppo di più entità, con una sola transizione. Crea una cache dei dai lato Client riducendo drasticamente la necessità di continui round-trip clientserver per recuperare dati già presenti lato Client alla transizione da una pagina ad un altra. Permette di estendere il modello con metodi, proprietà ed eventi personalizzati, è opensource cos altro volete? EntityManager E l oggetto che permette, lato Client, di accedere ai dati e crearne una cache Breeze si crea una sua struttura di Metadati, un file json che ricava con l Action Metadata nel controller che si crea, per poter navigare all interno della struttura dei dati che preleva Tipicamente si recuperano i dati da un database, o da un qualsiasi servizio di persistenza remoto, tramite una query eseguita con EntityManager; si presentano questi dati all utente tramite i meccanismi messi a disposizione dalle View, KnockouJS è uno di questi; si abilita la possibilità di manipolare questi dati con tutte le operazioni CRUD possibili e periodicamente si salvano le modifiche in sospeso con una sola transizione verso il database. EntityManager è sia un gateway per il servizio di persistenza dei dati che una cache delle entità su cui si intende lavorare lato Client. Gli oggetti interrogati e salvati sono entità mantenute nella Cache di EntityManager; queste entità possono entrare nel nostro EntityManager a seguito di una query, oppure a seguito di un operazione di inserimento lato client, o da un altro EntityManager della nostra App.

Queste entità liberano la cache, escono dal nostro EntityManager a seguito di un intervento da parte nostra, oppure perché contrassegnate come cancellate dopo un operazione di persistenza dei dati. La cache di EntityManager è interrogabile allo stesso modo in cui si interrogano i dati sul server remoto, con la sola unica grande differenza che è locale, quindi nessun round-trip Client-Server! Entity Un entità rappresenta un oggetto significativo nel modello della nostra applicazione. Potrebbe trattarsi di semplici dati, di relazioni fra entità (Cliente e relativi Ordini), di regole (una proprietà richiesta per convalidare il dato). Un entità in Breeze è un oggetto con le proprietà dei dati e le proprietà di navigazione che restituiscono entità correlate. Oltre alle normali proprietà relative ai dati, stringhe numeri, valori in genere, sono presente proprietà di navigazione fra le entità correlate nella cache di EntityManager. L esempio classico è costituito dall anagrafica Cliente con i relativi Ordini. Un entità Breeze è costituita anche da un suo kernel, una entity-ness, che rappresenta il suo entityaspect che serve al motore di Breeze per gestire l entità stessa. E possibile intervenire su questo kernel e influenzare il comportamento di Breeze nel manipolare l Entity stessa (a vostro rischio e pericolo). L aspetto più importante di una Entity è il suo EntityState. Questa proprietà indica se si tratta di un nuovo oggetto che è stato aggiunto, oppure se si tratta di un oggetto già presente ma che è stato modificato. E possibile esaminare i valori originali di un oggetto preesistente e ripristinare l entità al suo stato originale chiamando l istruzione entityaspect.rejectchanges(). Data Binding Breeze si basa principalmente sulle proprietà di Binding per intercettare le modifiche apportare lato client alle entità, il che significa che le proprietà che si vogliono trattare devono essere di tipo observable. Le proprietà in Breeze ovviamente lo sono. In ambito.net, lo sappiamo, questo meccanismo è garantito dall evento PropertyChanged, ma in JavaScript non vi è alcun meccanismo standard che implementi questa funzionalità. Ogni framework adotta la propria implementazione (KnockuotJS, AngularJS, BackboneJS, etc.). Breeze è in grado di lavorare con tutti questi framework, lasciando a noi la libertà di scegliere quello che più ci aggrada.

Query E possibile recuperare i dati da un server remoto componendo una query nella sintassi indicata da Breeze ed eseguendola attraverso un oggetto EntityManager var query = breeze.entityquery().from("coaches").where("name", "startswith", "A").orderBy("Name"); var manager = new breeze.entitymanager(servicename); manager.executequery(query).then(querysucceeded).fail(queryfailed); La prima cosa che possiamo notare è che si tratta di una chiamata asincrona, il metodo executequery restituisce una promise e invoca il metodo querysucceded nel caso l operazione vada a buon fine, oppure il metodo queryfailed in caso contrario. Breeze risolve questa query dentro con una richiesta HTTP GET, tipicamente si tratta di un servizio WebAPI con endpoint opportunamente configurato verso il nostro servizio di persistenza dei dati (SQL Server, MongoDB,..). La sintassi O-Data della query è supportata da WebAPI, ma anche da WCF e altri servizi non necessariamente.net compatibili. Ovviamente è possibile scrivere anche query complesse, sempre sfruttando la sintassi indicata da Breeze Salvataggio dei Dati Breeze aggiunge, modifica, elimina le entity nella cache di un EntityManager, mai direttamente sulla fonte dati remota. Tutto quello che fa è modificare l EntityState di una Entity. Tutte le modifiche vengono conservate e gestite nella cache sino alla chiamata del metodo SaveChanges() del nostro EntityManager.

manager.savechanges().then(savesucceeded).fail(savefailed); Ancora una volta possiamo notare che si tratta di un metodo asincrono che restituisce una promise, nel modo del tutto equivalente a quanto visto in precedenza per il recupero dei dati attraverso l esecuzione di una query. Ho già detto in precedenza che Breeze è in grado di persistere dati di una singola entità, o un batch di più entità fra loro relazionate, tutto in un unica transizione, consentendo un notevole risparmio di tempo ed un inutile round trip. Metadata Il Metadata di Breeze descrive i tipi di entità, e le relative relazioni fra di esse, in un modello di dati. Breeze necessita di questi metadati per comunicare con il servizio di persistenza durante l esecuzione di query. Si tratta di un insieme di informazioni che Breeze richiede autonomamente al server e che vengono restituite in formato json puro. Grazie a questi metadati creare un nuovo oggetto all interno di un entità diventa un operazione estremamente semplice con Breeze var newcoach = manager.createentity('coach', {CoachName='New Hero');

Promise Vs Callback Chiunque abbia scritto un minimo di codice JavaScript avrà scritto qualcosa di simile function getarticoli(callback, errorback){ $.ajax({ ); url: "/mywebapp/allspares.json", datatype: "json", success: function(data) {, // Sfrutto la callback per gestire la risposta della chiamamta ajax if (data.spares) { // OK: Abbiamo recuperato i dati, quindi possiamo invocare la callback if (typeof callback == "function" { callback(data.spares); else if (typeof errorback == "function") { errorback(new Error("Nessun Articolo Trovato"); error: function(jqxhr, textstatus, errorthrown) if (typeof errorback == "function") { errorback(errorthrown); La funzione getarticoli() dell esempio non ritorna nessun valore. L uso delle callback ci obbliga a scrivere codice strettamente accoppiato; dobbiamo conoscere esattamente dove inserire la chiamata alla callback per sortire l effetto desiderato e questo ci preclude la strada al riutilizzo del codice che stiamo scrivendo, cosa che a noi programmatori sfaticati e pigri non piace affatto! Per nostra fortuna le nuove librerie JavaScript ci offrono un alternativa alle callback, ovvero le promise, una promessa.

Una promise è un oggetto che rappresenta il valore di un azione asincrona, una cambiale per informazioni. Lo strumento messo a disposizione da jquery per implementare il meccanismo delle promise è l oggetto Deferred. L esempio riportato sopra, con l uso delle promise diventa function getarticoli(){ // Creo un'istanza dell'oggetto Deferred var deferred = new $.Deferred(); // Non faccio altro che invocare la mia funzione tramite Ajax... esattamente come prima $.ajax({ url: "/mywebapp/allspares.json", datatype: "json", success: function(data) { if (data.spares) { deferred.resolve(data.spares); else { deferred.reject(new Error("Nessun Articolo Trovato"));, error: function(jqxhr, textstatus, errorthrown) { deferred.reject(errorthrown); ); // Restituisco la promessa che rappresenta l'anagrafica articoli return deferred.promise(); La differenza fondamentale rispetto al primo approccio è la presenza di un valore di ritorno, cosa assolutamente non prevista nella versione basata sulle callback.

L oggetto che viene restituito è la cambiale, ovvero la promessa che il nostro utente potrà utilizzare per ottenere le informazioni che appunto gli abbiamo promesso, non appena queste saranno disponibili. La Deferred è il meccanismo con cui gestisco la promessa; posso creare una promessa che poi restituisco al mio utente, proprio come se lavorassi in maniera asincrona. Sarà l utente, avendo ora a disposizione questo oggetto, a collegare ad esso una callback per accedere ai valori richiesti: getarticoli().then (function (spare) { for (var i = 0, l = spares.length, i <l, i + +) { //... code code code and code more ); Si potrebbe obiettare dicendo che alla fine è ancora una callback quella che mi serve. Certamente! Ma a invocare e consumare la callback ora è il codice che ha invocato il tutto, la mia funzione non è assolutamente accoppiata con esso; in questo modo abbiamo astratto la funzione di estrazione articoli e possiamo riutilizzarla ognivolta che ci tornerà comodo, decidendo di volta in volta quale funzione attaccare tramite callback. La libreria che ci permette di gestire le promise è Q.js

Function Modules in RequireJS La caratteristica principale di RequireJS è la possibilità di definire un modulo come funzione. Se in un primo momento questo può sembrare una caratteristica piuttosto semplice, come in effetti lo è, ci sono alcuni aspetti pratici in cui tornare una funzione come modulo può rivelarsi piuttosto utile. L implementazione di una funzione come modulo è piuttosto semplice // random.js define(function(){ ); return function(min, max){ return Math.floor((Math.random()*max)+min); Dopo di che il modulo può essere richiamato nel modo seguente: require(['random'], function(random){ console.log(random(1,10)): ); Un modulo può essere utilizzato come mezzo conveniente per creare uno specifico tipo di oggetto su una entità in base a determinate condizioni. Prendiamo questo semplice esempio che, dato uno specifico ruolo, restituisce un implementazione corrispondente della View // app/views/editors/editorfactory.js define(function(require){ var editors = { 'admin' : require('editors/admineditorview'), 'user' : require('editors/usereditorview'), 'guest' : require('editors/guesteditorview'), // additional implementations... ; return function(role){ try {

); return new editors[role]; catch(error) { throw new Error('Unknown Role Specified.'); Il ViewModels può semplicemente invocare il modulo per recuperare l appropriata implementazione della View in base al ruolo specificato define(function(require){ var factory = require('editors/editorfactory'); return Backbone.View.extend({ render: function(){ //... view rendering this.editor = factory(this.model.get('role')); this.editor.render(); ); ); La definizione di funzioni come modulo semplifica notevolmente l implementazione del codice, consentendo una scrittura del codice più semplice, facilmente testabile e manutenibile.

Fonti http://www.html5italia.com/articoli/html5/creare-single-page-application-aspnet-mvc-durandaljs.aspx http://www.randomthink.net/blog/2012/10/callbacks-and-promises/ http://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-promises-are-functional-nodes-biggestmissed-opportunity/ http://www.ericfeminella.com/blog/2013/01/06/function-modules-in-requirejs/