01 · Problem
Wofür braucht man das?
Asynchrone oder mehrfache Werte sollen produziert, transformiert und unabhängig abbestellt werden können.
02 · Denkmodell
Das mentale Modell
Jede Subscription besitzt ihren eigenen closed-Zustand und Teardown. Ein Operator erstellt lediglich ein neues Observable, das die Quelle abonniert.
Verwaltet Cold-Source-Subscriptions mit unabhängiger Terminierung und genau einmaligem Teardown. Die Operatorauswahl ist bewusst klein. Hot-Multicasting, Backpressure und Scheduler benötigen zusätzliche Verträge.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Producer erhält einen sicheren Observer pro Subscription.
- next liefert Werte nur solange diese Subscription offen ist.
- error oder complete schließen sie genau einmal.
- unsubscribe führt den Teardown idempotent aus.
- Operatoren leiten Werte und Fehler an ihre eigenen Subscriber weiter.
04 · Bauteile
Die entscheidenden Verträge
SimpleObservable / SimpleSubscriptionVerwaltet unabhängige Cold-Source-Ausführung und Teardown.map / filterTransformiert oder filtert Werte und reicht Endsignale weiter.05 · Selbst bauen
Selbst implementieren
Implementiere zuerst Subscription-Lifecycle und sichere Observer, bevor Operatoren hinzukommen.
- Observer mit next, error und complete definieren.
- Pro subscribe einen lokalen closed-Schalter und idempotenten Teardown erzeugen.
- Operator-Callbackfehler in den Error-Kanal übersetzen.
type Observer<T> = {
next(value: T): void;
error(error: unknown): void;
complete(): void;
};
class Subscription {
private closed = false;
constructor(private teardown: () => void) {}
unsubscribe() {
if (this.closed) return;
this.closed = true;
this.teardown();
}
}06 · Verifizieren
Was solltest du testen?
- Unsubscribe eines Subscribers beeinflusst keinen zweiten Subscriber.
- Teardown läuft auch bei wiederholtem Unsubscribe genau einmal.
- Nach error oder complete werden keine weiteren Signale geliefert.
Selbst ausprobieren
Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.
Unsubscribe eines Subscribers beeinflusst keinen zweiten Subscriber.
Ansatz vergleichen
Dein Test sollte beim gezielten Verletzen der Invariante fehlschlagen und nach der Korrektur wieder bestehen. Halte den Aufbau deterministisch und prüfe ein beobachtbares Ergebnis.
07 · Grenzen
Kompromisse und Stolperfallen
- Cold Observables isolieren Subscriber, starten Producer aber mehrfach.
- Hot Multicasting teilt Arbeit und benötigt gemeinsamen Lifecycle sowie Backpressure-Regeln.
- Eine kleine API ist lehrreich, ersetzt nicht Scheduling und Operatorbreite von RxJS.
Die Operatorauswahl ist bewusst klein. Hot-Multicasting, Backpressure und Scheduler benötigen zusätzliche Verträge.
08 · Weiterdenken
Quellcode und verwandte Ideen
yarn tsx packages/reactivity/examples/basic.ts