AngularAtlasAusg. 22.2

Kap. 07Architektur der Anwendung43 / 75

Fehler: @boundary & ErrorHandler

Der neue @boundary-Block ab v22.2, der globale ErrorHandler, HTTP-Fehler und Fehler aus resource.

v22 ~0 Min. Lesezeit Offizielle Doku

Eine gute Fehlerstrategie hat Schichten: Vorhersehbare Fehler behandelst du lokal (eine Meldung neben den Daten), übergreifende zentral (ein Interceptor), und alles, was durchrutscht, landet in einem globalen ErrorHandler, der es protokolliert. Neu in v22.2: Der @boundary-Block isoliert die Rendering-Fehler eines Bereichs, sodass ein Fehler in einem Widget nicht die ganze Seite kaputt macht.

Die Schichten

Wo du welche Art von Fehler behandelst:

  Vorhersehbarer HTTP-Fehler (404, 422)  → im Store/in der Komponente: resource.error(), eine Meldung für die Nutzer
  Übergreifender HTTP-Fehler (401, 500)  → Interceptor (Weiterleitung zum Login, Toast, Retry)
  Rendering-Fehler eines Bereichs        → @boundary (v22.2, Developer Preview)
  Alles andere, was nicht abgefangen wird → globaler ErrorHandler (Log + Telemetrie)
  Formularvalidierung                    → Signal Forms (errors(), keine Exceptions)

@boundaryv22Developer Preview

<!-- v22.2 (developer preview): isoliert Rendering-Fehler eines Bereichs -->
@boundary {
  <app-price-widget [price]="price()" />
  <app-recommendations />
} @error (let error = $error; let reset = $reset) {
  <app-error-card [message]="error.message" (retry)="reset()" />
}

<!-- Mehrere @error-Blöcke mit `when`-Bedingungen — der erste Treffer gewinnt -->
@boundary {
  <app-report />
} @error (let e = $error; when e instanceof PermissionError) {
  <p>Du hast keinen Zugriff auf diesen Bericht.</p>
} @error (let e = $error; let retry = $reset) {
  <p>Etwas ist schiefgelaufen. <button (click)="retry()">Erneut versuchen</button></p>
}
LiveEin Fehler in einem Widget, isoliert mit @boundary
Mit @boundary
Preis: 1299.50 RON
Der Rest der Seite
Der umgebende Inhalt funktioniert weiter. Zähler: 0
Hake „ungültige Daten“ an: Das Widget wirft beim Rendern einen Fehler, aber nur sein Bereich wird ersetzt. Der Rest (der Zähler) funktioniert weiter.
Developer Preview

@boundary und die ErrorBoundary-APIs (ErrorDetails, onError bei createComponent) sind mit @developerPreview 22.2 markiert. Du kannst sie nutzen, aber die Syntax kann sich noch ändern. Ein abgefangener Fehler wird weiterhin an ErrorHandler gemeldet.

Globaler ErrorHandler

import { ErrorHandler, inject } from '@angular/core';

export class AppErrorHandler implements ErrorHandler {
  private readonly log = inject(ErrorLog);
  private readonly telemetry = inject(Telemetry);

  handleError(error: unknown): void {
    this.log.add(error);
    this.telemetry.captureException(error); // Sentry, App Insights, dein eigenes Backend
    console.error(error);
  }
}

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideBrowserGlobalErrorListeners(),                  // window.onerror + unhandledrejection → ErrorHandler
    { provide: ErrorHandler, useClass: AppErrorHandler },
  ],
};
LiveDer echte ErrorHandler dieser Seite
  • Noch kein Fehler. Drücke einen Button — der Fehler erreicht AppErrorHandler, der in app.config.ts registriert ist.
Beide Buttons werfen unbehandelte Fehler. Sie erreichen AppErrorHandler (core/error-handling), der sie in einem Store ablegt.

HTTP-Fehler

// Interceptor für übergreifende Fehler
export const errorInterceptor: HttpInterceptorFn = (req, next) => {
  const router = inject(Router);
  const toasts = inject(ToastService);

  return next(req).pipe(
    catchError((err: HttpErrorResponse) => {
      if (err.status === 401) router.navigate(['/login']);
      else if (err.status >= 500) toasts.show('Der Server hat Probleme. Versuche es später erneut.', 'bad');
      return throwError(() => err); // den Aufrufer auch reagieren lassen
    }),
  );
};

Dynamische Komponenten: onError

// Für dynamisch erzeugte Komponenten (v22.2): onError
const ref = viewContainer.createComponent(Widget, {
  onError: (error, details) => {
    console.warn('Das Widget', details.declarationType.name, 'ist fehlgeschlagen', error);
    this.vcr.clear(); // durch einen Fallback ersetzen
  },
});

Fehler aus resource und httpResource

Eine Resource wirft den Fehler nicht weiter. Sie hält ihn in ihrem Zustand: status() wird 'error', und error() sagt, was passiert ist. Achtung: value() im Fehlerzustand zu lesen wirft. Deshalb prüft das Template zuerst hasValue() oder error().

readonly user = httpResource<User>(() => `/api/users/${this.id()}`);

// erst der Fehler, dann der Wert: value() wirft im Fehlerzustand
@if (user.error(); as e) {
  <p role="alert">Das Profil konnte nicht geladen werden.</p>
  <button (click)="user.reload()">Erneut versuchen</button>
} @else if (user.hasValue()) {
  <h2>{{ user.value().name }}</h2>
} @else {
  <app-skeleton />
}

Fehler, die nicht durch Angular laufen

Manche Fehler entstehen nicht in Code, den Angular ausführt: ein setTimeout in einer Bibliothek, ein Promise, das ohne catch abgelehnt wird. provideBrowserGlobalErrorListeners() hört auf die Window-Events error und unhandledrejection und schickt sie ebenfalls an den ErrorHandler, damit du einen Ort für alle hast. Neue Projekte haben es bereits in app.config.ts.

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideBrowserGlobalErrorListeners(), // error + unhandledrejection aus window → ErrorHandler
    { provide: ErrorHandler, useClass: AppErrorHandler },
  ],
};

Was du an den Server schickst

Ein ErrorHandler, der nur in die Konsole schreibt, hilft in Produktion nicht, denn niemand sieht die Konsole des Nutzers. Schick Fehler an einen Logging-Dienst, aber mit Bedacht:

  • Deduplizieren. Derselbe Fehler in einer Schleife kann tausende Berichte pro Minute erzeugen. Merke dir kürzlich gesendete Meldungen.
  • Keine personenbezogenen Daten. Keine Tokens, Formularinhalte oder URLs mit E-Mail-Adressen senden. Schick Meldung, Stack und Route.
  • Die App nicht blockieren. Sende mit navigator.sendBeacon oder mit einem Request, der selbst nicht werfen kann.

Wiederholungen mit wachsender Pause zeigt Fortgeschrittenes RxJS: Operatoren höherer Ordnung; eine Seite, die beim Server-Rendering mit 404 antworten muss, Servertauglicher Code.

Häufige Stolperfallen

  • Verschluckte Fehler: Ein catchError(() => of([])) ohne Logging macht Bugs unsichtbar.
  • Ein Toast für jeden Fehler: Die Nutzer bekommen 5 Meldungen für ein einziges Problem. Zentralisiere und dedupliziere.
  • Ein ErrorHandler, der selbst wirft: Hat dein Handler einen Bug, verlierst du alle Fehler. Halte ihn einfach und sicher.
  • @boundary fängt keine Fehler aus Event-Handlern oder aus asynchronem Code ab — nur aus dem Rendering. Diese erreichen ErrorHandler.

Spickzettel

// Rendering: einen Bereich isolieren (v22.2, Developer Preview)
@boundary { <app-widget /> } @error (let e = $error) { <p>Widget nicht verfügbar</p> }

// lokal: neben den Daten, die fehlgeschlagen sind
catchError((e) => { this.error.set(e); return of(null); })

// Resources: der Fehler ist Zustand, keine Exception
res.error()   res.hasValue()   res.status() === 'error'   res.reload()

// global: alles, was durchrutscht, landet hier
provideBrowserGlobalErrorListeners()
{ provide: ErrorHandler, useClass: AppErrorHandler }

Kap. 07 · 0 von 7 abgeschlossen

Lektion abgeschlossen?

Markiere sie, dann erscheint sie auf deiner Karte: im Inhaltsverzeichnis und auf der Startseite.

Wird automatisch markiert, sobald du die ganze Lektion gelesen hast.

  1. Ordnerstruktur
  2. Shared vs. Feature
  3. Interfaces & Modelle
  4. State Management mit Signals
  5. Styleguide & Namensgebung
  6. Barrels, Aliase & Grenzen
  7. Fehler: @boundary & ErrorHandler
Deine ganze Karte ansehen

Alle 75 Seiten · tippen zum Filtern

  • 01Was ist neu in Angular 21 & 22Alle wichtigen Änderungen in v21 und v22 in Kürze, mit Link zur Seite, die sie jeweils erklärt.Start
  • 01Deine erste App, Schritt für SchrittEine Leseliste, von einer leeren Komponente bis zur fertigen App — Signals, @for, Inputs und Outputs, ein Service und ein Formular, Schritt für Schritt.Start
  • 01Schnelle Entscheidungen„Wohin damit?“, „Signal oder Observable?“, „Shared oder Feature?“ — kurze Antworten auf Alltagsfragen.Start
  • 01Angular-Interviewfragen60 echte Interviewfragen für Junior, Mid und Senior, mit der passenden Antwort, der Nachfrage und den Warnsignalen. Dazu ein Probeinterview.Start
  • 02Standalone & BootstrapWie eine App ohne NgModule startet: bootstrapApplication, app.config.ts, imports in der Komponente.Moderne Grundlagen
  • 02Data Binding & EventsInterpolation, Property- und Attribut-Bindings, Events mit $event und Tastenfiltern und wie [( )] aufgebaut ist — was in das DOM geht und was zurückkommt.Moderne Grundlagen
  • 02Control Flow: @if, @for, @switchDie Block-Syntax, die *ngIf/*ngFor/ngSwitch ersetzt, mit track, @empty und Exhaustive Checks.Moderne Grundlagen
  • 02@let und die neuen Template-AusdrückeLokale Variablen mit @let, Arrow Functions, Spread, Regex, instanceof, Kommentare in Tags.Moderne Grundlagen
  • 02@defer — Lazy Loading in TemplatesSchwere Komponenten nur laden, wenn sie gebraucht werden: Trigger, Prefetch, Placeholder, Loading, Error.Moderne Grundlagen
  • 02Class- & Style-BindingsWarum [class.x] und [style.x] ngClass und ngStyle abgelöst haben (mit automatischer Migration ab v21).Moderne Grundlagen
  • 02Komponenten-Styles & Kapselung:host, die drei Kapselungsmodi, Theming mit CSS-Variablen und warum ::ng-deep der letzte Ausweg ist.Moderne Grundlagen
  • 02Pipes: wann und wiePure vs. Impure Pipes, eigene Pipes und wie du zwischen Pipe, computed() und Methode wählst.Moderne Grundlagen
  • 03signal() und computed()Die reaktiven Grundbausteine: beschreibbarer Zustand, abgeleiteter Zustand, Gleichheit, untracked und Regeln zur Immutability.Signals & Reaktivität
  • 03effect() — wann ja, wann neinMit Signals synchronisierte Seiteneffekte: localStorage, Logging, imperative APIs. Und ihre Stolperfallen.Signals & Reaktivität
  • 03linkedSignal() — editierbarer abgeleiteter ZustandEin Signal, das sich zurücksetzt, wenn sich seine Quelle ändert, das du aber auch manuell setzen kannst.Signals & Reaktivität
  • 03resource, rxResource, httpResourceAsynchrone Daten als Signals: status, value, error, reload, automatischer Abbruch. Stabil seit v22.Signals & Reaktivität
  • 03debounced() — verzögerte SignalsDie „Debounce“-Variante eines Signals, ohne RxJS. Perfekt für die Suche.Signals & Reaktivität
  • 03Listen: suchen, filtern, sortieren, blätternEine Kette von computed-Signals, die nur neu berechnet, was sich geändert hat — mit den Filtern in der URL, damit ein Link dieselbe Ansicht öffnet.Signals & Reaktivität
  • 03Observables von null anWas ein Observable ist, subscribe und unsubscribe, die Operatoren, die du jede Woche brauchst, cold vs. hot — und wann ein Signal reicht.Signals & Reaktivität
  • 03Signals ↔ RxJStoSignal, toObservable, takeUntilDestroyed, outputFromObservable — und wann RxJS weiterhin die richtige Wahl bleibt.Signals & Reaktivität
  • 04input() und output()Inputs als Signals (required, transform, alias) und typisierte Outputs. Daten nach unten, Events nach oben.Komponenten: Kommunikation
  • 04model() — Two-Way-BindingBanana-in-a-Box [( )] mit einer einzigen API. Wann du es nutzt und wann input + output besser ist.Komponenten: Kommunikation
  • 04viewChild & contentChildQueries als Signals: viewChild, viewChildren, contentChild, contentChildren, die Option read.Komponenten: Kommunikation
  • 04Lifecycle & DestroyRefWelche Hooks in der Signals-Ära noch zählen, afterNextRender, DestroyRef und typisiertes ngOnChanges.Komponenten: Kommunikation
  • 04Content Projectionng-content mit select, mehrere Slots, Standardinhalt und die Falle der bedingten Projektion.Komponenten: Kommunikation
  • 04ng-template & ngTemplateOutletTemplates als Werte: Render Props in Angular, typisierter Kontext und Anpassen von Komponenten.Komponenten: Kommunikation
  • 05Smart vs. DumbContainer vs. Presentational: wer den Zustand hält, wer nur anzeigt und wie du die beiden sauber trennst.Komponenten-Design
  • 05Generische Komponenten <T>Eine korrekt typisierte DataTable<T> oder Select<T>, mit Templates für Zellen.Komponenten-Design
  • 05Dynamische KomponentenNgComponentOutlet, createComponent mit inputBinding/outputBinding und ein Dashboard, das aus einer Konfiguration gebaut wird.Komponenten-Design
  • 05Direktiven & Host-KompositionAttribut-Direktiven, die host: {}-Metadaten und die Directive Composition API (hostDirectives).Komponenten-Design
  • 05Eigene Formular-ControlsFormValueControl (Signal Forms) vs. ControlValueAccessor: eine Sternebewertung, in beiden Varianten.Komponenten-Design
  • 05Change DetectionOnPush ist ab v22 der Standard, zone.js entfällt ab v21. Was das Rendering auslöst und wie du dir nicht die Finger verbrennst.Komponenten-Design
  • 06inject() & @Service()Der neue @Service()-Decorator ab v22, inject() vs. Konstruktor und der Injection-Kontext.Dependency Injection
  • 06Provider & die Injector-HierarchieRoot vs. Route vs. Komponente, useClass/useValue/useFactory/useExisting und die Modifier optional/self/skipSelf.Dependency Injection
  • 06InjectionToken & provideX()Typisierte Konfiguration, provideFeature()-Funktionen, makeEnvironmentProviders und Initializer.Dependency Injection
  • 06injectAsync() — Lazy ServicesLade einen schweren Service erst, wenn du ihn brauchst, mit Prefetch im Leerlauf.Dependency Injection
  • 07Ordnerstrukturcore / shared / features, was in welchen Ordner gehört und wie ein Feature von innen aussieht.Architektur der Anwendung
  • 07Shared vs. FeatureWann du eine Komponente nach Shared verschiebst und (vor allem) wann NICHT. Eine konkrete Checkliste.Architektur der Anwendung
  • 07Interfaces & ModelleInline-Interface oder eigene Datei? DTO vs. Domänenmodell, type vs. interface, wohin damit.Architektur der Anwendung
  • 07State Management mit SignalsEinfache Signal-Stores, Fassaden, lokaler vs. globaler Zustand und wann du NgRx brauchst.Architektur der Anwendung
  • 07Styleguide & NamensgebungDie aktuellen offiziellen Konventionen: Dateinamen ohne Suffixe, protected, readonly, Reihenfolge der Member.Architektur der Anwendung
  • 07Barrels, Aliase & Grenzenindex.ts, Pfad-Aliase, die öffentliche API eines Features und Abhängigkeitsregeln, die sich automatisch prüfen lassen.Architektur der Anwendung
  • 07Fehler: @boundary & ErrorHandlerDer neue @boundary-Block ab v22.2, der globale ErrorHandler, HTTP-Fehler und Fehler aus resource.Architektur der Anwendung
  • 08Modernes Routing & Lazy LoadingloadComponent, Child Routes, Parameter als Inputs und Parameter-Vererbung (neuer Standard in v22).Routing
  • 08Guards & ResolvercanActivate, canMatch, canDeactivate und resolve als Funktionen, mit Redirects über UrlTree / RedirectCommand.Routing
  • 09Signal Forms — die GrundlagenFormulare auf Basis von Signals: form(), [formField], schemabasierte Validierung. Stabil seit v22.Formulare
  • 09Signal Forms — fortgeschrittenEigene und feldübergreifende Validierung, async/HTTP mit Debounce, dynamische Listen, disabled/hidden, wiederverwendbare Schemas.Formulare
  • 09Typisierte Reactive FormsTypisierte FormGroup, nonNullable, FormArray — und wie sie neben Signal Forms bestehen.Formulare
  • 10HttpClient, Interceptors & die API-SchichtHttpClient ohne Setup (v21), Fetch als Standard (v22), funktionale Interceptors und eine API-Schicht mit DTO-Mapping.HTTP & Daten
  • 11Performance — eine ChecklisteWas wirklich zählt: OnPush + Signals, track, @defer, Lazy Routes, Bilder, Bundles und Hydration.Qualität & Performance
  • 11Testen mit VitestVitest ist ab v21 der Standard-Runner. TestBed, Komponenten mit Signals, Services, HTTP und Harnesses.Qualität & Performance
  • 11DevTools: ein Blick in deine AppChrome DevTools und Angular DevTools Schritt für Schritt: was jedes Panel zeigt, mit Übungen, die auf dieser Website funktionieren.Qualität & Performance
  • 11Angular AriaHeadless, barrierefreie Komponenten, die du nach Belieben stylst: Tabs, Accordion, Menü, Listbox...Qualität & Performance
  • 12SSR, Prerendering & Render ModesWann auf dem Server gerendert wird, wann beim Build und wann nur im Browser: RenderMode pro Route, app.routes.server.ts und die echten Kosten.SSR & Hydration
  • 12Hydration: Event Replay & inkrementellWie der Browser das Server-HTML übernimmt, ohne es neu zu rendern: vollständige Hydration, Event Replay, @defer (hydrate on …) und Mismatch-Fehler.SSR & Hydration
  • 12Servertauglicher Codewindow gibt es auf dem Server nicht: PLATFORM_ID, afterNextRender, DOCUMENT, TransferState, der HTTP-Cache und PendingTasks.SSR & Hydration
  • 13Micro FrontendsWann es sich lohnt, eine App in mehrere Deployments aufzuteilen und wann es nur Komplexität ist: Native Federation, Module Federation, iframes, Web Components.Architektur im großen Maßstab
  • 13Web Components mit Angular ElementscreateCustomElement: eine Angular-Komponente, die überall als HTML-Tag nutzbar ist, plus Kommunikation zwischen Apps über Events und BroadcastChannel.Architektur im großen Maßstab
  • 13Monorepo, Bibliotheken & GrenzenEin Workspace mit mehreren Apps und Bibliotheken: ng generate library, Nx, Secondary Entry Points, Publishing und Abhängigkeitsregeln.Architektur im großen Maßstab
  • 13Hexagonale Architektur (Ports & Adapters)Eine Domäne ohne Angular, Ports als abstrakte Klassen und austauschbare Adapter: HTTP, localStorage oder In-Memory, ohne die UI anzufassen.Architektur im großen Maßstab
  • 14Signals unter der HaubeDer reaktive Graph: Producer und Consumer, Push-Pull, warum computed lazy und glitch-frei ist, das Diamond-Problem und wann Effects laufen.Fortgeschrittene Reaktivität
  • 14Fortgeschrittenes RxJS: Operatoren höherer OrdnungswitchMap, mergeMap, concatMap und exhaustMap an einem Live-Diagramm, dazu Retry mit Backoff, shareReplay und wie du Leaks vermeidest.Fortgeschrittene Reaktivität
  • 14NgRx SignalStoreState Management im großen Stil auf Signals: withState, withComputed, withMethods, rxMethod, Entities und Hooks — und wann ein einfacher Store reicht.Fortgeschrittene Reaktivität
  • 14Zustandsautomaten mit SignalsKeine unmöglichen Zustände mehr: ein typisierter Automat auf Signals, mit Übergängen, Guards und einem Live-Zustandsdiagramm.Fortgeschrittene Reaktivität
  • 15WebSockets: Echtzeit, die das Netz überstehtEin typisierter Socket als Signals: Reconnect mit Backoff und Jitter, Heartbeat, ein Postausgang im Offline-Modus und SSR-Sicherheit.Echtzeit & offline
  • 15Optimistische Updates & RollbackEine sofortige UI, die ehrlich bleibt: Snapshot und Rollback, Antworten in falscher Reihenfolge, Idempotenzschlüssel.Echtzeit & offline
  • 15Offline-first: Service Worker & CachingDer Angular Service Worker: Caching-Strategien, Update-Hinweise und ein Postausgang für Änderungen, die offline entstehen.Echtzeit & offline
  • 16Web WorkersSchwere Berechnungen, ohne die UI zu blockieren: ein echter Worker in der Seite, Message Passing und wann es sich nicht lohnt.Fortgeschrittene UI & Performance
  • 16Riesige Listen: Virtual Scroll100.000 Zeilen ohne Ruckeln: CDK Virtual Scroll, itemSize, trackBy und die Alternativen (Paginierung, Infinite Scroll).Fortgeschrittene UI & Performance
  • 16Moderne Animationen & View Transitionsanimate.enter und animate.leave statt des veralteten @angular/animations, CSS-Transitions und View Transitions bei der Navigation.Fortgeschrittene UI & Performance
  • 16Memory Leaks finden und behebenSubscriptions, Timer und Listener, die ihre Komponente überleben – wie du sie in den DevTools findest und schließt.Fortgeschrittene UI & Performance
  • 17Sicherheit: XSS, Sanitizing & CSPWas Angular automatisch gegen XSS tut, wann bypassSecurityTrust gefährlich wird, dazu CSP mit Nonce, Trusted Types und XSRF.Sicherheit & Globalisierung
  • 17Authentifizierung: Tokens & RefreshEin Interceptor, der das Token anhängt, bei 401 einmal erneuert und die wartenden Requests wiederholt — dazu, wo du das Token aufbewahrst.Sicherheit & Globalisierung
  • 17OAuth 2.1 & OpenID Connect mit PKCEDer Authorization-Code-Flow mit PKCE Schritt für Schritt: Verifier und Challenge, State und Nonce, das ID-Token und warum ein BFF sicherer ist.Sicherheit & Globalisierung
  • 17Internationalisierung (i18n)$localize, das i18n-Attribut, ICU plural/select, ein Build pro Sprache vs. Übersetzungen zur Laufzeit und Formatierung nach Locale.Sicherheit & Globalisierung