Servizi contro fabbriche in Angular

EDIT 2016. Nota che questo post, che è un repost di un post del 2015, riguarda Angular 1. Non faccio più frontend quindi nessuna garanzia che questo post sia rilevante per Angular 2 ;).

Uno dei miei compagni di classe Hack Reactor e io abbiamo recentemente costruito una calcolatrice per il trattamento della pressione alta per Moxe Health, un’eccitante azienda Rock Health che sta costruendo un sistema di integrazione di database e API che permetterà a qualsiasi sviluppatore di accedere alle cartelle cliniche elettroniche di qualsiasi ospedale nella rete di Moxe. Sono entusiasta di parlare di Moxe e del progetto in un altro post. Abbiamo costruito il front-end dell’app in Angular, un potente framework front-end con data binding e altre fantastiche caratteristiche. Una cosa che ci ha confuso era quando usare i servizi contro le fabbriche. Stack Overflow ha un buon thread sulla differenza tra i due, ma lascia fuori alcune analogie che penso siano utili agli sviluppatori che stanno ancora cementando la loro conoscenza di Javascript.

In questo post, imparerete la differenza tra i due.

TLDR – fabbriche e servizi hanno praticamente la stessa funzionalità in termini di capacità di istanziare e incapsulare metodi e proprietà, proprio come l’istanziazione funzionale e i modelli di istanziazione pseudoclassici hanno capacità simili. Non c’è una preferenza nella comunità Angular per l’uso dell’uno o dell’altro. Le ricette di fabbrica e di servizio sono solo zucchero sintattico sopra la ricetta del fornitore. Quindi la domanda che dovresti farti non è di solito “dovrei usare fabbriche o servizi?” è “dovrei usare l’istanziazione funzionale o l’istanziazione pseudoclassica?”

A parte questa comprensione di alto livello, la differenza più significativa è che come risultato della differenza nei loro modelli di istanziazione, le fabbriche possono restituire primitive e funzioni, ma i servizi no.

Primitive, funzioni e oggetti, oh mio!

Guarda questo JSFiddle. Credito a Epokk per aver fornito la maggior parte del codice. Ho fatto un paio di modifiche che, ancora una volta, aiutano davvero gli sviluppatori nuovi di Angular ad approfondire la differenza qui. Se siete nuovi a JSFiddle, è uno strumento che vi permette di testare facilmente le interazioni tra i vostri file javascript, html e css. Quindi puoi giocare con il codice, e non sovrascriverà il codice originale nel link.

Sia il servizio che il factory in questo esempio hanno la stessa funzionalità di restituire la stringa “Hello World!”. La differenza è come lo fanno.

Il servizio istanzia un oggetto e assegna la funzione che restituisce “Hello World!” alla proprietà “sayHello” di quell’oggetto:

this.sayHello = function() { return "Hello, World!" };

Il metodo viene poi invocato nel controller: helloWorldFromService.sayHello().

La fabbrica restituisce una funzione che restituisce “Hello World!”:

return function() { return "Hello, World!" };

La funzione viene poi invocata nel controllore: helloWorldFromFactory(). Notate come il riferimento della fabbrica punta alla funzione restituita, piuttosto che alla proprietà di un oggetto il cui valore è una funzione, come nell’esempio del servizio. Un servizio non potrebbe mai fare questo, perché un servizio deve istanziare un oggetto vuoto il cui riferimento all’interno del corpo della funzione di servizio è ‘this’. I servizi restituiscono sempre oggetti.

Ecco la parte delle factory che può confondere. La factory può anche restituire un oggetto che ha un metodo ‘sayHello’, proprio come il servizio:

return { sayHello: function() { return "Hello, World!" } };

Che invochereste nel controller esattamente come invochereste la funzione sayHello del servizio: helloWorldFromFactory.sayHello().

Quest’ultimo formato di fabbrica è utile quando volete avere più metodi in una fabbrica:

return { sayHello: function() { return "Hello, World!" }, sayGoodbye: function() { return "Goodbye, World!" } };

Ancora una volta, la chiave qui è non farsi prendere dal fatto che state codificando in Angular, e ricordare che le differenze tra servizi e fabbriche sono per la maggior parte le stesse delle differenze tra istanza pseudoclassica e istanza funzionale.

Codice sorgente per i curiosi

Ecco il codice sorgente di Angular, che dimostra che i servizi &factories sono stratificati sopra la caratteristica più generale dei providers:

//provider function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) { throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); } return providerCache = provider_; } //factory function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } //service function service(name, constructor) { return factory(name, ); }

Entrambi i servizi e le factory creano singleton. Modelli di eredità funzionali di base vs. pseudoclassici qui. La fabbrica restituisce qualsiasi cosa restituisca il factoryFn.

Il servizio restituisce un’istanza di una pseudo-classe. Il costruttore della pseudo-classe è passato al costruttore di servizi di Angular service(). Il fatto che il costruttore venga passato al servizio costruttore di servizi (return $injector.instantiate(constructor)) può confondere, ma basta pensarlo come return new constructor().

Buona codifica!

Leave a Reply