Im JSF Umfeld ist die Registrierung eines globalen Exception Handlers (über die faces-config) eine einfache Möglichkeit alle auftretenden Fehler innerhalb der Anwendung dem User auf einheitlichem Wege darzustellen. Auch Angular 2 bietet eine solche Möglichkeit Fehler nicht einfach nur „unsichtbar“ in der Console verschwinden zu lassen
Update 05.10.2016 auf Angular 2 Final
Class ExceptionHandler
Die zentrale Anlaufstelle für Fehler jeglicher Art in Angular 2 ist die Klasse „ErrorHandler“ (angular2/core). Diese sorgt dafür, dass jegliche auftretenden Fehlermeldungen in die Konsole geschrieben werden. Wollen wir den User aber direkt über solche Fehlersituationen benachrichtigen können wir dies natürlich über das Abfangen von Fehler unmittelbar in unserer Anwendung tun und die Meldungen an entsprechender Stelle in der Oberfläche ausgeben. Damit verteilen wir aber die Logik, wie wir mit Fehlern umgehen wollen, innerhalb der ganzen Anwendung. Eine einfache alternative dazu ist die Bereitstellung eines eigenen Exception Handlers indem wir von der Angular Klasse „ErrorHandler“ ableiten
@Injectable() export class GUIExceptionHandler extends ErrorHandler { handleError(exception: any, stackTrace?: any, reason?: string) { //custome error handling } }
Das alleine reicht allerdings nicht aus damit unsere Anwendung diesen auch verwendet. Hier kommt nun die mächtige Dependecy Injection von Angular ins Spiel. Angular bietet uns die Möglichkeit Einfluss darauf zu nehmen welche konkrete Implementierung für einen bestimmten Typ injiziert wird. Ein guter Startpunkt tiefer in diese Technik ein zu steigen ist die offizielle Dokumentation: dependency-injection
Wir nutzen nun die „provide“ Funktion um die Standard Implementierung des Exception Handlers durch unsere eigene zu ersetzen:
import { NgModule, ErrorHandler} from '@angular/core'; ... @NgModule({ imports: [...], declarations: [...], providers: [ ... { provide: ErrorHandler, useClass: AppExceptionHandler } ], bootstrap: [AppComponent], }) export class AppModule { }
Nun werden alle Fehlermeldungen die innerhalb der Anwendung auftreten an unseren ExceptionHandler weiter gegeben. Hier haben wir die Möglichkeit ganz individuell auf entsprechend Fehler zu reagieren und Meldungen an den User raus zu geben. Im Zusammenspiel einer eigenen Komponente und eine zentralen Services hier ein Beispiel:
Dabei ist zu beachten das das Re-Rendering der Anzeige nach einem Fehler nicht automatisch durchgeführt wird, dieses muss im ErrorHandler manuell getriggert werde. Dazu lassen wir uns im Konstruktor eine Injector-Instanz liefern und können über diese bei auftretendem Fehler die Referenz auf die Application erhalten um ein Rendering zu triggern:
this.injector.get(ApplicationRef).tick();
Auch fachliche Fehler lassen sich mit dieser Technik nahtlos integrieren. Im Java Umfeld deklarieren wir häufig für solche Fälle eine eigene Ableitung der Exception-Klasse, die bei Bedarf von der Anwendung ausgelöst werden kann. In Angular / JavasScript könnte dies so aussehen:
export class ApplicationException extends Error{ constructor(public message:string, public cause?:Error) { super(message); } } ... function methodWithError(){ ... throw new ApplicationException("...") }
Einmal mehr zeigt sich das die Dependy Injection von Angular 2 ein mächtiges Instrument ist um unsere Anwendung flexibel zu gestalten und wiederkehrende Aufgaben zentral zu implementieren.