Am 14. September 2017 haben wir eine überarbeitete Fassung unserer Datenschutzrichtlinie veröffentlicht. Wenn Sie video2brain.com weiterhin nutzen, erklären Sie sich mit diesem überarbeiteten Dokument einverstanden. Bitte lesen Sie es deshalb sorgfältig durch.

Cross-Plattform-Apps mit Cordova, Ionic, TypeScript und Visual Studio

Definition eines Services

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Controller sollten keine Daten verwalten. Dies geschieht in Services. Wie man solche Services programmiert, zeigt dieser Film.
13:34

Transkript

In meiner App habe ich mir eine Modell-Klasse erzeugt, die alle Informationen zu einer nicht stattgefundenen Ausgabe hält. Nun könnte ich diese Klasse, dieses Modell, direkt in meinem Controller nutzen. Wenn ich mir meinen Controller anschaue, dann sieht es aktuell so aus, dass ich im Moment immer, wenn jemand einen neuen Eintrag hinzufügt, eigentlich die Beschreibung wegwerfe und nur den Preis in einer Variablen hier in einem Feld aufsummiere. Ich könnte also hingehen und in diesem Controller ein Array von diesen Modell-Klassen halten, und jedes Mal, wenn jemand eine neue Eingabe tätigt, ein neues Element erzeugen und dies diesem Array hinzufügen. Das werde ich aber nicht machen, denn Controller sollten das Model nur beschaffen. Dieses sollten sie aber nicht direkt machen, sondern über einen Zwischenhändler, in der Regel über einen sogenannten Service. Der Vorteil besteht darin, dass ich später noch mich dazu entscheiden kann, mein Modell auf einem anderen Weg zu beschaffen. Was bedeutet das? Im Moment würde ich zum Beispiel einfach ein Array nehmen, um meine Einträge zu speichern. Später möchte ich aber vielleicht diese Einträge in einer Datenbank speichern. Wenn das der Fall ist, dann müsste ich überall dort, wo ich diese Modell-Klassen benötige, eine Code-Änderung machen. Das möchte ich vermeiden, und möchte die nur einmal an zentraler Stelle machen: in meinem Service. Und so einen Service, den lege ich mir jetzt einmal an. Dazu lege ich mir eine neue TypeScript-Datei an, und zwar im Ordner "savedItems", denn das wird mein SavedItemsService. Und genauso nenne ich den auch, also eine Datei vom Typ "TypeScript", und die heißt "SavedItemsService". Au, da habe ich mich verschrieben. Da benenne ich die Datei schnell um und packe noch ein "S" davor. Und dieser Service, der ist jetzt erstmal innerhalb des Name-Spaces "App.SavedItems" zu Hause. Der heißt also genauso wie mein Ordner. Und jetzt möchte ich als allererstes eine Schnittstelle für diesen Service definieren, ein Interface. Und dieses Interface, das kann ich dann später ganz toll für IntelliSense und so weiter nutzen. Dazu schreibe ich "export interface", und das nenne ich "ISavedItemsService". Und in diesem Interface definiere ich jetzt, dass es eine Methode "getTotal" gibt. Und was diese Methode macht, ist: Die gibt mir eine Zahl zurück, die ist also vom Typ "number". Und zwar wird hier berechnet, was die aktuelle Summe der gesparten Einträge ist. Außerdem habe ich eine Methode "getSavedItems". Die gibt mir, wie Sie schon erwarten können, die Liste der bisher gesparten Einträge zurück. Und das ist vom Typ "Array", und zwar ein generisches Array vom Typ "SavedItem". Ich finde, das ist ein ganz tolles Feature von TypeScript, dass ich generische Arrays oder auch andere generische Datentypen und Methoden nutzen kann. Dann haben wir eine Methode "addItem". Und an "addItem" übergeben wir die Beschreibung, die zum Typ "string", und wir übergeben den Preis. Der ist vom Typ "number". Dieses Interface, das möchte ich natürlich jetzt implementieren. Ich wurde hier übrigens darauf hingewiesen, dass ich hier implizit den Typ "any" zurückgebe. Und ich nutze jetzt hier das void-Schlüsselwort, um anzugeben, dass das hier gar nichts zurückgeben wird. So, jetzt werde ich dieses Interface implementieren, indem ich schreibe: "class SavedItemsService". Und dann nutze ich das implements-Schlüsselwort, um auszudrücken, dass ich hier den Service "ISavedItemsService" implementiere. Und jetzt wird sich Visual Studio kurz beschweren gleich. Und zwar beschwert sich Visual Studio darüber, dass ich diese Schnittstelle nicht implementiere. Und das stimmt auch. Also sollten wir hier Abhilfe schaffen. Zum einen werde ich jetzt ein Feld anlegen, nämlich das Feld "savedItems". Und das ist vom Typ "Array", und zwar ein generisches Array vom Typ "SavedItem". Dieses Feld an sich, das hilft mir jetzt noch nicht, mein Interface zu erfüllen. Aber das brauche ich später, um einfach diese Einträge zurückzugeben, und zwar mit der Methode "getSavedItems". Und getSavedItems, das gibt jetzt eben genau diese saved items zurück. Ich sollte diese allerdings auch irgendwo initialisieren. Und das kann ich zum Beispiel in einem Konstruktor erledigen. Und in diesem Konstruktor, da definiere ich, dass die savedItems einfach ein neues Array vom Typ "SavedItem" sind. Jetzt habe ich zwar schon diese Methode hier implementiert, es fehlt aber noch "addItem" und "getTotal". Fangen wir mit "addItem" an. "addItem" erhält übergeben die Beschreibung vom Typ "string", und den Preis vom Typ "number". Und was wir hier im Endeffekt machen, ist Folgendes. Ich füge zu meiner Liste von gespeicherten Einträgen einen neuen Eintrag hinzu. Das kann ich über die push-Methode erledigen und übergebe hier einen neuen Eintrag vom Typ "SavedItem". Und "SavedItem" hat einen Konstruktor, das ist schon sehr praktisch, der eben genau eine Beschreibung und einen Preis entgegennimmt. Insofern war diese Methode hier jetzt auch sehr einfach zu implementieren. Fehlt also nur noch "getTotal". "getTotal" soll mir ja vom Typen "number" die Summe zurückgeben. Was muss ich also machen? Im Endeffekt lege ich mir hier eine temporäre Variable an. Die ist vom Typen "number", und der weise ich Null zu. Und dann brauche ich hier eine Schleife. Und in dieser Schleife iteriere ich von Null, und zwar solange i kleiner als die Länge der gespeicherten Einträge ist. Natürlich muss ich das auch hier dann entsprechend erhöhen. Und innerhalb der Schleife, Sie sehen das schon, das ist kein Hexenwerk, sage ich einfach: "total += this.savedItems" an der Position "i". Und hier nehmen wir die Eigenschaft "price". Ich finde es übrigens sehr bemerkenswert, wie gut unter TypeScript die IntelliSense funktioniert. Sie sehen hier also: Ich bekomme genau angegeben, welche Eigenschaften meine Klasse hat, und auch nur diese Eigenschaften, keine geratenen oder erfundenen anderen Eigenschaften. So, im Moment ist das immer noch rot. Das ist rot, weil wir nichts zurückgeben. Also geben wir "total" zurück. Damit habe ich diese Schnittstelle vollständig erfüllt. Und ich kann jetzt meinen SavedItemsService zu den Angular- Services hinzufügen. Das funktioniert im Endeffekt wie folgt. Ich schreibe hier unten "angular.module", hole mir damit also eine Referenz auf das Modul "savedIt", und jetzt füge ich hier einen Service hinzu. Und dieser Service, der erhält den Namen "savedItemsService". Und ich übergebe die Konstruktor- Funktion "SavedItemsService". Wenn Sie in der Vergangenheit bereits mit direktem JavaScript und Angular entwickelt haben, dann werden Sie sich hier vielleicht fragen, warum ich keine Factory benutzt habe. Der Punkt ist: Eine Factory unter TypeScript zu erzeugen, ist relativ aufwendig. Ein Service hingegen ist sehr einfach zu erzeugen, weil ich einfach nur eine Klasse schreibe und später diese Klasse dann an den Service übergebe. Intern geschieht Folgendes. Wenn Sie einen Service unter Angular erzeugen, dann wird von dem einmal eine Instanz erzeugt. Und diese Instanz wird dann überall dort genutzt, wo Sie diesen Service brauchen. Angular sorgt also dafür, dass Sie einen Singleton haben, für diesen Service. Wenn Sie eine Factory haben, dann würden Sie beim Initialisieren bereits ein fertiges Objekt übergeben. Und dann muss Angular halt nicht mehr dafür sorgen, dass es ein Singleton ist, weil es halt nur das eine Objekt gibt, und es wird keines mehr daraus erzeugt. Der Unterschied ist also: Bei einer Factory hätte ich selber erst einmal das Objekt erzeugen müssen, und bei einem Service kann das Angular für mich bei Bedarf machen. Das geht mit TypeScript eben sehr einfach. Was jetzt noch bleibt, ist, diesen Service tatsächlich auch in meinem Controller zu benutzen. Und dazu wechsle ich hier zurück in den HomeController. Und hier mache ich nun Folgendes. Ich definiere jetzt hier im Konstruktor, dass ich, um zu funktionieren, einen Service brauche, nämlich den SavedItemsService. Der ist allerdings private und nicht public, "private savedItemsService". Und der ist vom Typ "App.SavedItems.ISavedItemsService". Nun sehen Sie hier: Ich sehe jetzt hier diese Schnittstelle. Und die sehe ich jetzt hier, weil ich eben das export-Schlüsselwort hier oben benutzt habe. Deswegen sehe ich diese Schnittstelle, und nicht diesen Service. Und nun gehe ich wie folgt vor. In meinem Konstruktor habe ich bisher schon das Feld "totalSaved" initialisiert, und zwar mit dem Wert "0". Ich habe dazu jetzt allerdings eine schöne Methode, nämlich an meinem SavedItemsService die Methode "getTotal". Diese Methode, die kann ich natürlich auch hier unten aufrufen. Hier sage ich also: "totalSaved" ist gleich "this.SavedItemsService". Falls Sie sich wundern, warum ich in meiner Klasse kein Feld für "SavedItemsService" erzeugen musste: Das liegt daran, dass ich hier "private" vorgeschrieben habe. Dann wird das Feld automatisch erzeugt. Damit er hier richtig rechnet, muss ich natürlich erst noch einen neuen Eintrag hinzufügen. Und das funktioniert, indem ich auf SavedItemsService die Methode "addItem" aufrufe. Und hier übergebe ich einfach "this.description" und "this.price". Zu guter Letzt muss ich jetzt sowohl Modell als auch den Service noch in meiner HTML-Datei verweisen. Ich gehe also in die index.html und werde jetzt hier noch die entsprechenden Links einsetzen. Und zwar habe ich jetzt hier an neuen Dateien hier einmal die Datei "SavedItem.js". Das ist also unter "js". "savedItems" und dann "savedItem.js". Im Moment kennt Visual Studio das noch nicht, weil ich noch nicht erneut kompiliert habe. Und erst nach dem Kompilieren ist die IntelliSense halt soweit, weil erst dann per TypeScript-Compiler die JavaScript-Datei erzeugt wird. So, wenn ich jetzt kompiliere, dann müssten wir auch hier unten im Ordner "js" die Dateien haben. Da sind sie: "SavedItem" und "SavedItemsService". Und hier sehe ich auch schon einen kleinen Tippfehler. So, jetzt klappt auch die IntelliSense. Das muss ich gleich also neu kompilieren. Und das geschieht am einfachsten, indem ich meine Anwendung einmal starte. Wir sollten jetzt im Debugger sehen, dass die Anwendung immer noch läuft. Ich spare mir also mal was: einen Burger für 0,99. Und das sieht schonmal gut aus. Was sparen wir uns noch? Wir sparen uns noch einen Schokoriegel. Und der kostet 1,49. Und auch hier wurde korrekt gerechnet. Bedeutet also: In diesem Video haben wir unsere Logik zur Verwaltung von unserem SavedItem-Modell in einen SavedItemService gepackt. Dieser Service, der hat eine Methode erhalten, um alle Einträge zurückzugeben. Der hat eine Methode bekommen, die zwei Strings entgegennehmen und dann einfach einen neuen Eintrag erzeugen. Und er hat eine Methode zur Berechnung der Summe erhalten. Jetzt hätte ich, als kleine Anmerkung, dieses export-Schlüsselwort auch vor den Service stellen können. Ich mache das allerdings ganz gerne, dass ich mir explizit ein Interface nochmal darüberschreibe, und zwar genau aus diesem Grund, weil ich dann noch einmal sehr genau sehe, welche Methoden mein Service überhaupt zurückgibt.

Cross-Plattform-Apps mit Cordova, Ionic, TypeScript und Visual Studio

Steigen Sie in die App-Programmierung ein und kombinieren Sie die praktischen Tools.

2 Std. 45 min (23 Videos)
Derzeit sind keine Feedbacks vorhanden...
 
Exklusiv für Abo-Kunden
Erscheinungsdatum:14.11.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!