AngularJS – manuelles Bootstraping für asynchrone Initialisierungen

AngularJS kommt mit vielen „magischen“ Funktionen daher welche die Entwicklung und das Zusammenspiel vereinfachen, allem voran die Depedency Injection. Unsere Aufgaben als Entwickler um eine AngurJS Anwendung zu initialisieren beschränken sich auf die Einbindung der Bibliothek und die Deklaration einer ng-app Direktive. Aber was ist wenn wir unsere Anwendung mit Daten eines http-Services konfigurieren wollen bevor die Anwendung dem Benutzer zur Verfügung steht? An dieser Stelle steht AngularJS uns mit seinem strikten asynchronen Verhalten im Weg, bietet aber eine Ausweg: manuelles Bootstraping

Die normale Initialisierung einer AngularJS Anwendung findet ganz automatisch statt. Nachdem die HTML Seite geladen wurde (inklusive AngularJS Referenz) ermittelt Angular über die angular-app Direktive  die zu ladende Anwendung, erzeugt den Injektions-Mechanimus und erzeugt/lädt alle benötigten Objekte und Module. Innerhalb dieses Prozesses werden auch die .config und .app Funktionen der Referenzierten Module zur Initialisierung geladen. Aber selbst in diesen Methoden ist es uns  nicht möglich auf die Abarbeitung von asynchronen Anfragen zu warten (um zum Beispiel eine Konfiguration über http zu laden). Um ein solches Szenario dennoch zu realsieren bestehen mehrer Möglichkeiten

  • einen synchron xhr-Request stellen ohne http-Service  (xmlhttp.open(method, url, false))
    • syncrone Anfragen im main Thread sind deprecated
  • ui-router mit einem Mehrstufigem Template dessen Root-State mittels „resolve“ die benötigten Daten lädt
  • manuelle Bootstraping

Um ein manuelles Boostraping unserer AngularJS Anwendung zu realisieren müssen wir im ersten Schritt dafür Sorge tragen das AngularJS mit seinem Automatismus uns nicht zuvorkommt. Aus diesem Grund entfernen wir die ng-app Direktive aus unserer HTML-Seite:

Vorher: 
< html ng-app="AngularBootstraping">
Nachher:
< html>

Damit führt AngularJS keinerlei Initialisierung durch und es liegt an uns diese, nach Fertigstellung unserer Konfiguration, aus zu führen.  Ausgehend davon das unser Angular Modul den Namen: „AngularBootstraping“ trägt könnte eine solche Methode so aussehen:

(function () {
    "use strict";
    // Erzeugen einer Injector Instanz
    // dazu übergeben wir die von uns benötigten Module
    // inklusive 'ng' welches uns diverse Angular Objekte zur Verfügung stellt
    var initInjector = angular.injector(["ng", "AngularJSi18n.globalize.services", "AngularBootstraping.initialize"]);

    // den Injektor nutzen um manuelle Dependency Injection durch zu führen
    // und asyconre Initialisierungen durchführen, z.B:
    
    // 1. Initialisierung von Globalize über eine Factory
    var $window = initInjector.get("$window");
    var lang = $window.navigator.language || $window.navigator.userLanguage;
    var GlobalizeLanguageLoader = initInjector.get("GlobalizeLanguageLoader");

    // 2. KonfigurationsObjekt über Rest Schnittstelle laden
    var configPromise = initInjector.get("InitFactory").getConfig();
    var globalizePromise = GlobalizeLanguageLoader.loadLanguage(lang);
    
    // auf alle asychronen Requests warten:
    var $q = initInjector.get("$q");

    $q.all([configPromise, globalizePromise]).then(function(result){
        // die Ergebnisse unserer Initialisierung legen wir als Konstanten ab:
        angular.module("AngularBootstraping").constant("$config", result[0]);
        angular.module("AngularBootstraping").constant("$globalize", result[1]);
        
        // erst jetzt lassen wir AngularJS seine Initialisierung durchführen
        angular.bootstrap(document, ["AngularBootstraping"]); 
    });
    
})();

Damit stellen wir sicher dass alle unsere Aufgaben zur Initialisierung beim eigentlichen Programmstart bereits abgeschlossen sind. Wichtig: in einer Produktiven Umgebung sollte eine stabile Fehlerbehandlung implementiert werden, wenn einer der Schritte innerhalb der Initialisierung fehlschlägt (z.B. Rest-Services stehen nicht zur Verfügung)  findet keine Anzeige der Anwendung statt.

Asynchrone Requests sind ein wichtiger Bestandteil von AngularJS Anwendungen die ein anwenderfreundliches Handling sicherstellt. Wir sollten nur in unausweichlichen Situationen auf diese Initialisierung zurückgreifen da sie den Start der Anwendung entsprechend verzögert ohne das der Anwender über die aktiven Lade-Vorgänge informiert wird. Dennoch gibt es durchaus solche Situationen für die AngularJS, wie zu sehen, eine passende Lösung parat hält.

Advertisements

Über Dominik Mathmann
Dominik Mathmann arbeitet als Berater, Entwickler und Trainer bei der GEDOPLAN GmbH. Auf Basis seiner langjährigen Erfahrung in der Implementierung von Java-EE-Anwendungen leitet er Seminare, hält Vorträge und unterstützt Kunden bei der Konzeption und Realisierung von Webanwendungen vom Backend bis zum Frontend. Sein derzeitiger Schwerpunkt liegt dabei auf der Entwicklung von JSF-Anwendungen. Er sieht die stärker werdende Position von JavaScript-Frameworks jedoch positiv und beschäftigt sich darüber hinaus mit Webframeworks wie AngularJS.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: