Start / Seminare / Angular für erfahrene Entwickler
Modul
Reaktiver Datenabruf mit resource() und httpResource()
Modul 11 von 22 aus dem Seminar Angular für erfahrene Entwickler
5 Kapitel in diesem Modul-Video · Laufzeit
Für Teams
Die Videos zeigen, wie es geht. Die Schulung sorgt dafür, dass Ihr Team es danach tut.
Ein Video kann niemanden fragen, warum es ausgerechnet in Ihrem Repository nicht funktioniert. Es kann kein Team auf eine gemeinsame Konvention bringen. Und es setzt sich niemand freiwillig drei Tage hin. In der Schulung sind am Ende alle auf demselben Stand, gearbeitet wurde am eigenen Code, und die offenen Fragen sind entschieden — in ein paar Tagen statt irgendwann nebenbei.
Vorgespräch am Telefon · Programm nach Maß · ab 1 Tag (8 Unterrichtseinheiten) · Teilnahmezertifikat
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Reaktiver Datenabruf
0:00 Jetzt kommt eine Umkehrung, die beim ersten Mal ungewohnt ist und danach sehr einleuchtend. Bisher haben wir Daten abgerufen: Ich rufe auf, ich bekomme eine Antwort, ich schreibe sie irgendwohin. Eine Ressource wird nicht aufgerufen. Sie folgt einem Signal. Ändert sich der Filter, folgt die Abfrage — und bricht ab, was gerade noch lief.
0:20 Das löst nebenbei ein Problem, das die meisten selbstgebauten Lösungen haben und das fast nie auffällt.
Navigation, Daten und Formulare
0:27 Wir sind mitten im dritten Tag. Der Datenzugriff steht, jetzt machen wir ihn reaktiv — und schließen damit die Lücke zwischen dem Zustand aus Modul fünf und der Schnittstelle aus Modul zehn.
Ressourcen als reaktive Abfrage
0:39 Fangen wir mit der allgemeinen Form an. Die brauchen Sie nicht nur für HTTP — sie funktioniert für alles, was asynchron etwas liefert. Eine Ressource besteht aus zwei Teilen: einer Funktion, die die Parameter liefert und dabei Signals liest, und einer Ladefunktion. Ändern sich die Parameter, läuft die Ladefunktion erneut — und bekommt ein Abbruchsignal für die vorherige Anfrage mit.
1:03 Zurück bekommen Sie kein Versprechen, sondern eine Sammlung von Signals: Wert, Status, Fehler, Ladezustand. Denken Sie an einen Wasserhahn statt an einen Eimer. Sie holen nicht einmal Wasser und stellen es hin — Sie haben eine Leitung, und was ankommt, hängt davon ab, wie Sie gerade aufgedreht haben. Zwei Details sind hier entscheidend. Erstens: Die Parameterfunktion liest ein Signal. Genau dadurch wird die Ressource reaktiv — liest sie keines, passiert nie wieder etwas.
1:33 Zweitens: Das Abbruchsignal wird an die Anfrage weitergereicht. Das ist der Teil, den man in einer selbstgebauten Lösung fast immer vergisst, weil alles auch ohne ihn funktioniert. Fast immer. Und was dann passiert, sehen wir in Kapitel drei. Der Rest — Wert lesen, Status abfragen — ist normale Signal-Arbeit. Sechs Zustände, und ich möchte auf drei hinweisen, die man leicht übersieht. „Idle" heißt: keine gültige Anfrage — etwa weil ein Parameter noch fehlt.
2:03 Das ist kein Fehler, sondern ein legitimer Zwischenzustand. Der Unterschied zwischen „loading" und „reloading" ist praktisch: Beim einen haben sich die Parameter geändert, beim anderen hat jemand ausdrücklich neu geladen. In der Oberfläche darf das unterschiedlich aussehen. Und „local" heißt, der Wert wurde von Hand gesetzt — nützlich, wenn Sie nach einem Speichern das Ergebnis schon kennen.
2:27 Der erste Punkt ist der, der die ganze Sache lahmlegt: Die Parameterfunktion liest kein Signal, und die Ressource lädt nie neu. Sie sieht richtig aus und tut nichts. Der zweite ist der, der die Hauptfunktion aushebelt: Die Ladefunktion ignoriert das Abbruchsignal, und abgebrochene Anfragen laufen weiter. Und der dritte ist ein Laufzeitfehler mit Ansage: Der Wert wird gelesen, ohne vorher zu prüfen, ob es überhaupt einen gibt.
httpResource() im Einsatz
2:54 Für den häufigsten Fall — lesende HTTP-Abrufe — gibt es eine kürzere Form. Und die werden Sie in Ihren Anwendungen am meisten benutzen. Das ist der reaktive Aufsatz auf den HTTP-Zugriff. Sie übergeben eine Funktion, die eine Adresse oder ein Anfrageobjekt liefert. Für andere Antwortformate gibt es eigene Varianten — Text, Binärdaten.
3:16 Besonders praktisch ist die Option für eine Prüffunktion: Sie nimmt die Prüfung entgegen, von der wir im letzten Modul gesprochen haben, und bestimmt damit gleich den Ergebnistyp. Eine Einschränkung sollten Sie sich merken: Für schreibende Aufrufe ist das nicht gedacht. Ressourcen sind zum Lesen da. Was Sie hier sehen, ersetzt in Spurweite etwa dreißig Zeilen der alten Fassung — Ladezustand, Fehlerfeld, Abonnement, Aufräumen.
3:42 Worauf es ankommt: Die Funktion liest zwei Signals, Statusfilter und Suchtext. Damit folgt die Abfrage beiden. Niemand muss irgendwo aufrufen, wenn sich der Filter ändert; es gibt keinen Ort, an dem man das vergessen könnte. Das ist der eigentliche Gewinn — nicht die kürzere Schreibweise, sondern dass eine ganze Fehlerklasse verschwindet.
4:04 Drei Zweige, und keiner davon ist optional. Der Ladezustand, der Fehlerzweig und der Erfolgsfall. Man ist versucht, den mittleren wegzulassen — im Entwicklungsbetrieb tritt er ja nie auf. Genau das ist der Grund, warum er in vielen Anwendungen fehlt und der Benutzer bei einer Störung eine leere Seite sieht. Achten Sie auf die Reihenfolge: erst laden, dann Fehler, dann Erfolg. Und auf die Prüfung, ob überhaupt ein Wert da ist, bevor er gelesen wird.
4:32 Der erste Punkt ist eine Abgrenzung: Die Ressource wird zum Anlegen oder Ändern verwendet. Das ist nicht ihr Zweck, und es geht schief, sobald der Benutzer zweimal klickt. Der zweite ist derselbe Fehler wie eben, in anderer Form: Die Adresse wird gebaut, ohne ein Signal zu lesen, und friert ein. Und der dritte ist der, den ich gerade beschrieben habe: Der Fehlerfall fehlt im Template, und die Ansicht bleibt leer.
Konkurrierende Anfragen und Abbruch
4:57 Und jetzt der Teil, wegen dem dieses Modul wirklich existiert. Ein Fehler, den fast jede selbstgebaute Suche hat und den fast niemand je gesehen hat. Stellen Sie sich vor, jemand tippt schnell. Bei jedem Zeichen startet eine Anfrage — Sie haben also mehrere gleichzeitig unterwegs. Jetzt antwortet die ältere später als die neuere. In einer selbstgebauten Lösung schreiben beide in dasselbe Feld, und am Ende gewinnt die, die zuletzt ankommt — also die falsche.
5:26 Die Ressourcen-APIs brechen die vorherige Anfrage beim Parameterwechsel ab, damit kann das nicht passieren. Wer es selbst baut, muss diesen Fall ausdrücklich behandeln. Lesen Sie diese vier Schritte einmal langsam. Eingabe A, Eingabe B — so weit erwartbar. Dann Antwort B, und der Benutzer sieht das richtige Ergebnis. Und dann, eine halbe Sekunde später, Antwort A. Die überschreibt das richtige Ergebnis mit dem alten.
5:53 Der Benutzer sieht eine Trefferliste, die zu seiner Eingabe nicht passt — aber plausibel genug aussieht, dass er es nicht als Fehler erkennt. Er denkt, er hat sich vertippt, und tippt noch einmal. Das ist die Art Fehler, die nie gemeldet wird. Vier Gründe, und zusammen erklären sie, warum dieser Fehler jahrelang in einer Anwendung leben kann.
6:15 Auf schnellen Verbindungen tritt die Überholung praktisch nie ein — und Entwickler haben schnelle Verbindungen. Im Test mit festen Antworten gibt es keine Verzögerung, also auch kein Rennen. Der Fehler zeigt sich als falsche, aber plausible Trefferliste, nicht als Absturz. Und reproduzierbar wird er nur mit künstlicher Verzögerung, auf die man erst kommt, wenn man die Ursache schon vermutet.
6:38 Der erste Punkt ist die Konsequenz aus dem eben Gesagten: Der Fall wird nie getestet, weil er lokal nicht auftritt. Genau deshalb schreiben wir gleich einen Test dafür. Der zweite ist die häufigste Fehlform in selbstgebauten Lösungen: Ein eigener Abruf per Abonnement sammelt Ergebnisse, statt sie zu ersetzen — dann kommen sogar Treffer aus zwei verschiedenen Suchen zusammen in einer Liste.
7:00 Und der dritte ist die falsche Sicherheit: Der Abbruch wird angenommen, aber das Signal nicht weitergereicht.
Imperativ oder deklarativ entscheiden
7:06 Bleibt die Frage, die Sie einmal für Ihr Team entscheiden sollten — und dann konsequent anwenden. Die Regel ist erfreulich einfach: Lesen folgt dem Zustand, Schreiben folgt der Absicht. Lesende Abrufe, die von einem Zustand abhängen — Liste, Detail, Suche — gehören als Ressource modelliert. Schreibende Aufrufe folgen einer Absicht des Benutzers und bleiben ein gewöhnlicher Aufruf.
7:30 Der Grund ist inhaltlich, nicht technisch: Ein Lesevorgang darf wiederholt und abgebrochen werden, ein Schreibvorgang nicht. Diese Trennung gehört einmal entschieden und dann im ganzen Team gleich angewendet. Die zweite Zeile ist die wichtigste: bricht selbst ab gegen läuft zu Ende. Genau das ist der Grund für die Trennung.
7:50 Sie wollen nicht, dass ein Speichervorgang abgebrochen wird, weil der Benutzer inzwischen den Filter geändert hat. Die dritte Zeile ist der Komfortgewinn — Zustände eingebaut statt selbst geführt. Und die vierte macht es konkret: Liste, Detail und Suche links; Anlegen, Ändern, Löschen rechts. Wenn Sie sich diese vier Zeilen merken, brauchen Sie die Diskussion nie wieder zu führen.
8:13 Der erste Punkt ist das, was ohne eine festgehaltene Regel entsteht: Beide Muster stehen für denselben Zweck nebeneinander im Code. Der zweite ist ein Folgefehler, den man im Betrieb sofort sieht: Nach dem Schreiben wird die Liste nicht neu geladen und zeigt Altes. Die Ressource weiß ja nicht, dass sich etwas geändert hat — die Parameter sind dieselben.
8:33 Und der dritte ist Überbau: Eine Ressource für einen einmaligen Aufruf, der nie wieder laufen wird.
Übung
8:40 Stellen wir die Suche um — und schreiben den Test, der das Rennen sichtbar macht. Die Auftragssuche filtert nach Status und Suchtext. In der bisherigen Fassung wurde bei jeder Eingabe ein Aufruf gestartet und dessen Ergebnis in ein Feld geschrieben. Bei langsamer Verbindung erschien gelegentlich ein älteres Ergebnis — und in der Werkstatthalle ist die Verbindung oft langsam. Gemeldet wurde der Fehler nie.
9:03 Aufgefallen ist er, als eine Meisterin sich wunderte, warum ihre Suche nach einem Kennzeichen manchmal Aufträge zeigte, die nicht dazu passten. Das Lernziel nennt beide Hälften: lesenden Abruf an reaktiven Zustand koppeln, und das Verhalten bei konkurrierenden Anfragen nachweisen. Nachweisen, nicht behaupten. Das Erfolgskriterium verlangt deshalb einen Test, der belegt, dass eine verzögerte ältere Antwort nichts überschreibt.
9:29 Wer früh fertig ist, ergänzt die Prüfoption und lässt eine unvollständige Antwort abweisen — damit schließt sich der Kreis zum vorigen Modul, denn es ist dieselbe Prüfung an einem anderen Ort. Der erste Schritt ist ein Rückbau, und der fühlt sich gut an: den alten Abruf samt Ergebnisfeld entfernen. Dann die Kopplung an die Signals, dann die drei Zustände im Template.
9:51 Schritt vier ist der interessante — eine ältere Antwort künstlich verzögern und den Fall nachstellen. Das ist die Arbeit, die Sie sonst nie machen würden, und genau deshalb steht sie hier. Und Schritt fünf hält fest, was Sie gerade gelernt haben: ein Test, der ohne die Umstellung fehlschlägt. Der erste Punkt ist der, der die Reaktivität still aushebelt: Die Adresse wird einmal berechnet und liest danach kein Signal mehr.
10:16 Der zweite ist die halbe Arbeit: Der Test prüft nur den Erfolgsfall und nicht das Rennen — dann haben Sie einen Test, der genau das nicht abdeckt, wofür die Umstellung gemacht wurde. Und der dritte ist die Übertreibung: Das Speichern wird ebenfalls auf eine Ressource umgestellt. Im nächsten Modul geht es um Formulare — und um zwei Modelle, die eine Weile nebeneinander leben werden.
Dieses Modul als Schulung für Ihr Team
Das Video zeigt den Stoff. In der Schulung arbeitet Ihr Team damit — an Ihrem eigenen Code, mit Übungen und mit den Fragen, die ein Video nicht beantwortet. Sie wählen die Module aus Angular für erfahrene Entwickler, wir bauen daraus ein Programm.
6 Tage·ab 900 EUR netto pro Tag (bis 3 Teilnehmende) ·Termin nach Vereinbarung