Reaktives Programmieren gibt es in Angular doch erst seit Signals
此内容尚不支持你的语言。
Warum diese Aussage historisch falsch ist — und warum sie in echten Projekten gefährlich werden kann.
Der Denkfehler
Abschnitt betitelt „Der Denkfehler“Eine verbreitete Aussage lautet:
„Reaktives Programmieren gibt es in Angular doch erst seit Signals.“
Die Aussage klingt auf den ersten Blick plausibel.
Seit Angular 16 stehen APIs wie signal(), computed() und effect() sichtbar im Angular-Core. Reaktivität ist dadurch sprachlich und konzeptionell präsenter geworden. Wer erst mit dieser Angular-Generation tiefer eingestiegen ist, kann leicht den Eindruck bekommen: Vor Signals war Angular hauptsächlich komponenten- und klassenorientiert, danach wurde es reaktiv.
Das Problem ist: Diese Deutung verwechselt Sichtbarkeit mit Ursprung.
Signals haben Angular nicht reaktiv gemacht.
Signals haben Angular eine neue, framework-native Reaktivitätsprimitive gegeben.
Das ist ein wichtiger Unterschied.
Warum solche Aussagen gefährlich sind
Abschnitt betitelt „Warum solche Aussagen gefährlich sind“Der Satz ist nicht nur eine falsche historische Einordnung.
Er ist gefährlich, weil er in Projekten als bequeme Ausrede funktionieren kann.
Wenn Reaktivität angeblich erst mit Angular 16 entstanden ist, dann musste man sie in Angular 2, 4, 8, 12 oder 15 ja nicht lernen. Dann waren imperative Komponenten, manuelle Subscriptions, lokale Mutationen und unklare Datenflüsse nicht das Ergebnis schlechter Architekturentscheidungen, sondern angeblich der damalige Stand des Frameworks.
Das ist bequem.
Aber es ist falsch.
Solche Aussagen funktionieren oft wie eine Verteidigung gegen unbequeme Fragen:
- Warum wurde nie sauber mit
Observable-Streams gearbeitet? - Warum gibt es keine klaren ViewModels?
- Warum hängt Fachlogik in Components?
- Warum wird State manuell synchronisiert?
- Warum stehen überall
subscribe()-Blöcke? - Warum gibt es keine erkennbare Trennung zwischen Read-State und Commands?
- Warum ist das Template voller Logik?
- Warum ist Refactoring nach Jahren kaum noch möglich?
Die Antwort lautet dann nicht mehr:
„Wir haben das Paradigma nicht verstanden, nicht gelernt oder nicht priorisiert.“
Sondern:
„Das gab es damals ja noch gar nicht.“
Genau darin liegt die Gefahr.
Denn wenn die Diagnose falsch ist, werden auch die Entscheidungen falsch.
Der Schaden entsteht nicht im Satz, sondern in der Codebasis
Abschnitt betitelt „Der Schaden entsteht nicht im Satz, sondern in der Codebasis“Ein einzelner falscher Satz baut noch keine schlechte Architektur.
Aber wenn solche Sätze über Jahre Entscheidungen rechtfertigen, entstehen Codebasen, die irgendwann kaum noch beweglich sind.
Dann sieht ein Angular-Projekt nach sieben Jahren vielleicht so aus:
- Components mit tausenden Zeilen Code
- imperative Lade- und Fehlerzustände überall
- verschachtelte Subscriptions
- manuelle Synchronisation zwischen Feldern
- Services als globale Datenablagen
- Templates mit Funktionsaufrufen und versteckter Logik
- keine sauberen fachlichen Grenzen
- kein konsistentes State-Modell
- kaum testbare Presentation Logic
- hoher Aufwand für jede Änderung
- Angst vor Framework-Upgrades
- Abhängigkeit von alten Patterns, die nie bewusst gewählt wurden
Und dann entsteht der bittere Widerspruch:
Das Team ist im Framework eingeschlossen, hat aber dessen zentrale Konzepte nie sauber genutzt.
Das ist echter Framework-Lock-in.
Nicht, weil Angular grundsätzlich einsperrt.
Sondern weil die Codebasis so stark gegen das Framework-Paradigma gebaut wurde, dass jede Modernisierung teuer wird.
Die konkrete Wahrheit
Abschnitt betitelt „Die konkrete Wahrheit“Die korrekte historische Einordnung lautet:
Angular war nicht erst seit Signals reaktiv. Angular war seit Angular 2 stark Observable- und RxJS-geprägt. Signals ergänzen dieses Modell seit Angular 16 um eine framework-native, feingranulare Reaktivitätsprimitive.
Das ist die Wahrheit in einem Satz.
Und sie ist wichtig, weil sie die Verantwortung richtig verteilt.
Angular 2 bis 15 waren nicht „präreaktiv“.
Sie waren Observable-basiert.
Wer in dieser Zeit Angular komplett imperativ gebaut hat, hat nicht einfach nur „damaligen Angular-Stil“ geschrieben. Er hat wesentliche Konzepte des Frameworks ignoriert oder nur oberflächlich genutzt.
Das ist keine moralische Anklage.
Aber es ist eine wichtige technische Diagnose.
Die historische Pointe: Angular 2 war bereits der reaktive Bruch
Abschnitt betitelt „Die historische Pointe: Angular 2 war bereits der reaktive Bruch“Um den Denkfehler sauber zu verstehen, muss man Angular und AngularJS auseinanderhalten.
AngularJS war stark von $q, Promises, $http, $scope, $watch und dem Digest Cycle geprägt. Die AngularJS-Dokumentation beschreibt $q als Promises/A+-kompatible Implementierung von Promises und Deferred Objects.
Quelle: AngularJS Docs: $q
Das war die AngularJS-Welt: asynchrone Abläufe wurden häufig Promise-basiert modelliert und durch den Digest Cycle in die UI getragen.
Angular 2 war hier kein kleines Update.
Angular 2 war ein Bruch.
Bereits die alte Angular-2-Dokumentation beschreibt beim HTTP-Client, dass http.get() kein Promise zurückgibt, sondern ein Observable<Response> aus RxJS. Direkt danach erklärt die Dokumentation RxJS als eine von Angular unterstützte Bibliothek und sagt, dass Observables breit in Angular-Anwendungen genutzt werden.
Quelle: Angular v2 Archive: HTTP Client / RxJS library
Auch das Angular-2-Glossar beschreibt Observables als Teil von Angular selbst. Observables werden dort unter anderem mit Angulars Event-System und HTTP-Client verbunden.
Quelle: Angular v2 Archive: Glossary / Observable
Auch im Template-Binding war Angular 2 bereits reaktiv anschlussfähig. Die alte Angular-2-Dokumentation zum AsyncPipe beschreibt, dass der AsyncPipe ein Promise oder Observable akzeptiert, automatisch subscribed und die emittierten Werte weiterliefert.
Quelle: Angular v2 Archive: Pipes / AsyncPipe
Das ist der entscheidende historische Punkt:
Angular war nicht erst seit Signals reaktiv. Angular 2 war bereits die Abkehr von der AngularJS-Promise-Welt hin zu einer Observable-/RxJS-geprägten Architektur.
Signals kamen viel später.
Sie haben nicht den reaktiven Gedanken in Angular eingeführt. Sie haben ein weiteres reaktives Modell ergänzt: framework-näher, synchroner, feingranularer und stärker auf lokalen sowie abgeleiteten State ausgerichtet.
Die Chronologie ist deshalb nicht:
AngularJS: imperativ Angular 2 bis 15: nicht reaktiv Angular 16: endlich reaktiv
Sondern:
AngularJS: stark Promise-,
$q- und Digest-Cycle-geprägt Angular 2: Observable-/RxJS-basierter Neuanfang Angular 16: Signals als zusätzliche framework-native Reaktivitätsprimitive
Damit fällt der Mythos fachlich in sich zusammen.
Denn wer sagt:
„Reaktives Programmieren gibt es in Angular erst seit Signals.“
überspringt die zentrale Architekturentscheidung von Angular 2.
Angular 2 hat Observables nicht zufällig irgendwo geduldet. Angular 2 hat sie im HTTP-Client, in der Dokumentation, im Event-Modell und im Template-Binding sichtbar gemacht.
Das war kein Randdetail.
Das war ein Paradigmenwechsel gegenüber AngularJS.
Kurzchronologie
Abschnitt betitelt „Kurzchronologie“| Phase | Prägendes Modell | Bedeutung |
|---|---|---|
| AngularJS | $q, Promises, $http, $scope, $watch, Digest Cycle | Asynchronität wurde häufig Promise-basiert modelliert und über den Digest Cycle in die UI integriert. |
| Angular 2 | RxJS, Observables, Http, Event-System, AsyncPipe | Angular wechselte sichtbar zu einer Observable-/RxJS-geprägten Architektur. |
| Angular 16 | Signals, computed, effect, RxJS-Interop | Angular ergänzte eine framework-native, feingranulare Reaktivitätsprimitive. |
Diese Chronologie ist wichtig.
Signals sind nicht der Gegenentwurf zu AngularJS.
Angular 2 war bereits der Gegenentwurf zu AngularJS.
Signals sind der nächste Entwicklungsschritt innerhalb von Angular.
Auch heutiges Angular ist weiterhin Observable-basiert
Abschnitt betitelt „Auch heutiges Angular ist weiterhin Observable-basiert“Das Observable-Modell ist kein historischer Unfall, der später verschwunden wäre.
Die aktuelle Angular-Dokumentation beschreibt Observables weiterhin als Schnittstelle, mit der Angular typische asynchrone Operationen behandelt: HTTP nutzt Observables für Requests und Responses, Router und Forms nutzen Observables, um auf User-Input-Events zu reagieren.
Quelle: Angular Docs: Observables in Angular
Auch die aktuelle Angular-Dokumentation zum HttpClient sagt weiterhin, dass Request-Methoden RxJS-Observables zurückgeben.
Quelle: Angular Docs: Making HTTP requests
Die aktuelle API-Dokumentation des HttpClient zeigt Rückgabetypen wie Observable<T>, Observable<HttpEvent<T>> oder Observable<HttpResponse<T>>.
Quelle: Angular API: HttpClient
RxJS ist also nicht einfach eine Altlast aus der Vergangenheit.
Es ist weiterhin Teil des Angular-Alltags.
Was Signals wirklich eingeführt haben
Abschnitt betitelt „Was Signals wirklich eingeführt haben“Signals sind trotzdem nicht kleinzureden.
Angular 16 hat Signals eingeführt: eine neue Signals-Library in @angular/core und eine Interop-Schicht zu RxJS über @angular/core/rxjs-interop.
Quelle: Angular Blog: Angular v16 is here
Die aktuelle Signals-Dokumentation beschreibt Signals als System, das granular verfolgt, wie und wo State in einer Anwendung genutzt wird, damit Angular Rendering-Updates optimieren kann.
Quelle: Angular Docs: Signals
Typische Signal-APIs sind:
const count = signal(0);
const doubled = computed(() => count() * 2);
effect(() => { console.log('Count changed:', count());});Das ist eine andere Form von Reaktivität als ein RxJS-Stream.
Signals sind besonders stark bei synchronem, lokalem und ableitbarem State:
- UI-State
- lokale Component-Zustände
- abgeleitete Werte
- feingranulare Updates
- einfache Abhängigkeiten zwischen Werten
- bessere Lesbarkeit für bestimmte State-Beziehungen
RxJS ist dagegen besonders stark bei asynchronen Datenströmen:
- HTTP
- Router-State
- WebSockets
- Events
- Formulare
- Debouncing
- Cancellation
- Kombination mehrerer Quellen
- komplexe zeitliche Abläufe
Beides ist reaktiv.
Aber es löst unterschiedliche Probleme.
Angular selbst behandelt RxJS und Signals nicht als Entweder-oder
Abschnitt betitelt „Angular selbst behandelt RxJS und Signals nicht als Entweder-oder“Angular stellt eine eigene Interop-Schicht bereit, um RxJS und Signals miteinander zu verbinden.
Die aktuelle Doku zu @angular/core/rxjs-interop beschreibt toSignal(): Damit kann ein Signal erzeugt werden, das den Wert eines Observables verfolgt. Die Doku vergleicht dieses Verhalten mit dem async pipe, nur flexibler und auch außerhalb von Templates nutzbar.
Quelle: Angular Docs: RxJS interop with Angular signals
Auch das widerlegt den Mythos.
Wenn Signals die erste echte Reaktivität in Angular wären, bräuchte Angular keine offizielle Brücke zwischen Observables und Signals.
Diese Brücke existiert gerade deshalb, weil Angular historisch stark Observable-basiert ist und Signals dieses Modell nicht einfach ersetzen, sondern ergänzen.
Warum der Denkfehler entsteht
Abschnitt betitelt „Warum der Denkfehler entsteht“Der Denkfehler entsteht oft, weil viele Angular zwar benutzen, aber das reaktive Paradigma dahinter nie wirklich konsequent gelernt haben.
Man kann Angular sehr lange so schreiben:
this.http.get<User[]>('/api/users').subscribe((users) => { this.users = users;});Das funktioniert.
Es ist aber noch kein reaktives Architekturmodell.
Es ist häufig nur imperativer Code mit einem Observable am Anfang.
Reaktiver Angular-Code fragt nicht nur:
Wie bekomme ich den Wert?
Er fragt:
- Woher kommt der Zustand?
- Wie verändert er sich über Zeit?
- Was ist abgeleiteter State?
- Was ist ein Command?
- Was ist ein Read-Model?
- Was gehört ins ViewModel?
- Was soll das Template nur noch konsumieren?
- Welche Abhängigkeiten sollen explizit modelliert werden?
- Wo endet Presentation Logic?
- Wo beginnt Fachlogik?
RxJS war dafür lange vor Signals vorhanden.
Observable, map, switchMap, combineLatest, shareReplay, AsyncPipe, Facades, Stores und ViewModels waren nicht erst seit Angular 16 möglich.
Viele Teams haben diese Möglichkeiten nur nie konsequent genutzt.
Falsche Aussagen schützen schlechte Entscheidungen
Abschnitt betitelt „Falsche Aussagen schützen schlechte Entscheidungen“Technische Halbwahrheiten sind selten nur Wissenslücken.
In Projekten werden sie oft zu Schutzschildern.
Sie schützen alte Entscheidungen vor Prüfung. Sie schützen gewachsene Codebasen vor unangenehmen Fragen. Sie schützen Rollenbilder, in denen Frontend nur als UI-Schicht verstanden wurde. Sie schützen Teams davor, Dokumentation, Paradigmen und Framework-Entwicklung ernsthaft nachzuvollziehen.
Das Problem ist nicht, dass jemand etwas nicht weiß.
Das Problem beginnt, wenn aus Nichtwissen eine Architekturbegründung wird.
„Das ging damals nicht.“
ist eine starke Aussage.
Wenn sie falsch ist, verdeckt sie die eigentliche Ursache.
Vielleicht ging es doch. Vielleicht war es dokumentiert. Vielleicht war es sogar der empfohlene Weg. Vielleicht wurde es nur nicht gelernt, nicht verstanden oder nicht priorisiert.
Das ist unangenehm.
Aber für eine ehrliche technische Analyse ist genau diese Unterscheidung entscheidend.
Warum das Produkte trifft
Abschnitt betitelt „Warum das Produkte trifft“Schlechte Architektur bleibt nicht im Code.
Sie trifft das Produkt.
Wenn ein Angular-Frontend über Jahre imperativ, unstrukturiert und gegen reaktive Datenflüsse entwickelt wurde, wird jede fachliche Änderung teurer:
- neue Features dauern länger
- Fehler werden schwerer reproduzierbar
- Seiteneffekte werden unübersichtlich
- Refactorings werden riskant
- Tests bleiben oberflächlich
- UI-Zustände werden inkonsistent
- Releases werden vorsichtiger
- technische Schulden bestimmen die Produktplanung
Irgendwann entscheidet nicht mehr das Produkt, was gebaut wird.
Die Codebasis entscheidet, was noch bezahlbar ist.
Das ist der Punkt, an dem Architektur kein internes Entwicklerthema mehr ist.
Sie wird zum Produktproblem.
RxJS vs. Signals ist die falsche Debatte
Abschnitt betitelt „RxJS vs. Signals ist die falsche Debatte“Die interessante Frage ist nicht:
RxJS oder Signals?
Die bessere Frage lautet:
Welches Reaktivitätsmodell passt zu welchem Problem?
Ein HTTP-Request, der durch einen Suchbegriff ausgelöst wird und alte Requests abbrechen soll, ist oft ein sehr gutes RxJS-Problem.
Ein lokaler UI-Zustand, ein abgeleiteter Wert oder eine einfache State-Beziehung in einer Component ist oft ein sehr gutes Signal-Problem.
Ein Store kann beide Welten berühren.
Eine Facade kann Observables konsumieren und Signals exponieren.
Ein Signal kann aus einem Observable entstehen.
Ein Observable kann aus einem Signal entstehen.
Angular selbst stellt dafür Interop bereit. Das ist ein starkes Indiz dafür, dass Angular RxJS und Signals nicht als Entweder-oder betrachtet.
Die eigentliche Architekturfrage
Abschnitt betitelt „Die eigentliche Architekturfrage“Eine gute Angular-Architektur entsteht nicht dadurch, dass man überall signal() schreibt.
Sie entsteht durch saubere Zuständigkeiten.
Wichtiger als die konkrete API sind Fragen wie:
- Ist die Fachlogik vom Template getrennt?
- Gibt es ein klares ViewModel?
- Sind Commands und Read-State getrennt?
- Sind Datenflüsse nachvollziehbar?
- Sind Seiteneffekte kontrolliert?
- Ist abgeleiteter State wirklich abgeleitet oder manuell synchronisiert?
- Sind Components Konsumenten oder Müllhalden?
- Sind Services sauber geschnitten oder nur Manager-Klassen?
- Ist der Code testbar?
- Ist die Architektur verständlich?
Ob der konkrete State dann über RxJS, Signals, NgRx Signal Store oder eine Kombination modelliert wird, ist eine Implementierungsfrage.
Das Paradigma dahinter ist wichtiger als die API.
Die bessere Formulierung
Abschnitt betitelt „Die bessere Formulierung“Statt:
„Reaktives Programmieren gibt es in Angular erst seit Signals.“
besser:
„Angular war seit Angular 2 stark Observable- und RxJS-geprägt. Seit Angular 16 ergänzt Signals dieses Modell um eine framework-native, feingranulare Reaktivitätsprimitive.“
Diese Formulierung ist historisch korrekter.
Sie würdigt Signals, ohne die Jahre davor fachlich auszuradieren.
Und sie verhindert, dass alte Architekturentscheidungen nachträglich durch eine falsche Framework-Geschichte legitimiert werden.
Die bessere Frage
Abschnitt betitelt „Die bessere Frage“Statt zu sagen:
„Angular war damals eben nicht reaktiv.“
sollte man fragen:
„Welche reaktiven Konzepte standen uns damals zur Verfügung — und warum haben wir sie nicht genutzt?“
Das ist die unbequemere Frage.
Aber es ist die nützlichere.
Denn sie führt nicht zu Ausreden, sondern zu Lernen:
- Welche Paradigmen haben wir übersehen?
- Welche Patterns haben wir falsch eingesetzt?
- Welche Entscheidungen waren damals bewusst?
- Welche waren nur Gewohnheit?
- Welche Teile der Codebasis müssen wir stabilisieren?
- Welche Konzepte brauchen wir heute, um wieder beweglich zu werden?
Erst dann entsteht Architekturarbeit.
Nicht durch Schuldzuweisung.
Sondern durch präzise Diagnose.
Die Aussage
„Reaktives Programmieren gibt es in Angular doch erst seit Signals.“
ist historisch und fachlich falsch.
Angular war seit Angular 2 Observable- und RxJS-geprägt. Die offizielle Angular-2-Dokumentation beschreibt Observables im HTTP-Client, im Event-System und im AsyncPipe. Die aktuelle Angular-Dokumentation nutzt Observables weiterhin im HttpClient. Angular 16 hat Signals als neue, framework-native Reaktivitätsprimitive eingeführt — inklusive offizieller RxJS-Interop.
Signals sind daher keine Geburtsurkunde der Angular-Reaktivität.
Signals sind ein neues Kapitel.
Ein wichtiges Kapitel. Ein gutes Kapitel. Aber nicht Kapitel eins.
Und genau deshalb ist der Mythos gefährlich.
Er macht aus verpasstem Lernen eine Framework-Ausrede. Er macht aus Architekturversäumnissen historische Notwendigkeit. Er verhindert die Frage, die man in alten Angular-Codebasen stellen müsste:
Was davon war wirklich durch Angular begrenzt — und was haben wir nur nie sauber gelernt?
Diese Frage ist unbequem.
Aber ohne sie bleibt man nicht nur im Framework gefangen.
Man bleibt in der eigenen Vergangenheit gefangen.
Quellen
Abschnitt betitelt „Quellen“- AngularJS Docs: $q
- Angular v2 Archive: HTTP Client / RxJS library
- Angular v2 Archive: Glossary / Observable
- Angular v2 Archive: Pipes / AsyncPipe
- Angular Docs: Observables in Angular
- Angular Docs: Making HTTP requests
- Angular API: HttpClient
- Angular Blog: Angular v16 is here
- Angular Docs: Signals
- Angular Docs: RxJS interop with Angular signals
Quellen geprüft am 10. Juni 2026.