Gedankenanstoß: Warum ist RxJS unleserlich?
RxJS hat im Frontend-Bereich ziemlich an Popularität gewonnen, und viele Menschen verwenden es in Kombination mit React und VueJS. Dennoch kann das vollständige Eintauchen in den reaktiven Ansatz von RxJS zu sehr unleserlichem Code führen. Schauen wir uns an, warum das so ist.
RxJS hat das Konzept eines Observable, das uns Werte über die Zeit liefert. Man kann es sich als eine Variable vorstellen, die uns mitteilt, dass sich ihr Wert geändert hat, oder einfach als einen Stream. Alle möglichen Operationen können mit der .pipe-Methode darauf angewendet werden.
const value$ = new BehaviorSubject(9000)
const transformedValue$ = value$.pipe(
map(value => {
// ...
}),
filter(value => {
// ...
})
)
Soweit sieht alles gut aus – aber was, wenn wir komplexe Berechnungen haben oder mehrere Observables kombinieren müssen?
const transformedValue1$ = combineLatest([
value1$,
value2$
]).pipe(
switchMap(([value1, value2]) => {
const value3$ = // ...
return withLatestFrom(value3$).pipe(
map(value3 => {
// ...
})
)
}),
// ...
)
const transformedValue2$ = combineLatest([
transformedValue1$,
value4$
]).pipe(
map(([transformedValue1, value4]) => {
// ...
})
)
Wie man sieht, wird der Code ziemlich schnell verwirrend. Und dabei haben wir noch nicht einmal begonnen, der Pipe weitere Kombinatorik hinzuzufügen. Der Übeltäter hier ist die „Callback-Hölle”. Promises hatten dasselbe Problem mit verketteten .then-Aufrufen und der Rückgabe von Promises darin. Das führte zu viel Verschachtelung und schwer nachzuverfolgendem Code, da die Logik, die zusammengehören sollte, an Stellen mit unterschiedlichen Einrückungsebenen oder sogar gar nicht im selben .then-Block zu finden ist. Im obigen Beispiel sieht man, dass es eine Variable namens transformedValue1$ gibt, die nur existiert, um die Komplexität der gesamten Transformation aufzuteilen.
Wie haben Promises also das Callback-Hölle-Problem gelöst? JavaScript führte eine neue Syntax namens async/await ein. Anstatt .then zu verketten, kann einfach await verwendet werden, und der gewünschte Wert wird für uns „ausgepackt”. Die neue Syntax hat zuvor verketteten und verschachtelten Code in prozeduralen Code verwandelt.
promise
.then(value => {
return fetch(...).then(nestedValue => {
// ...
})
})
.then(value => {
// ...
})
// turns into
const value1 = await promise
const value2 = await fetch(...)
const value3 = await // ...
const value4 = await // ...
Wie zu sehen ist, gibt es keine Verschachtelung mehr und die Logik ist nicht mehr überall verstreut. Nun stellt sich die Frage: Können wir etwas Ähnliches für RxJS tun? Dazu können wir uns Svelte ansehen.
$: reactiveValue = doSomeStuff(foo, bar)
Damit wird reactiveValue neu berechnet, wann immer sich foo oder bar ändert. Wir können natürlich noch einen Schritt weiter gehen:
$: value1 = doSomeStuff(foo, bar)
$: value2 = value1 + 100
$: value3 = value2 > 9000 ? 'over 9000' : 'not enough power leveling'
$: value4 = // ...
Genau wie async/await es bei Promises getan hat, hat die unkonventionelle Syntax von Svelte das Callback-Hölle-Problem für RxJS gelöst. Genau genommen funktioniert alles mit einer .subscribe-Methode mit Svelte. RxJS hat also zufällig davon profitiert. Man kann sagen, dass $: syntaktischer Zucker für .subscribe ist – genau wie await syntaktischer Zucker für .then ist (await funktioniert bei allem, das eine .then-Methode hat, nicht nur bei Promises).
Der Ansatz von Svelte funktioniert jedoch nur in Svelte, da wir den Svelte-Compiler benötigen, um den Code in normales JavaScript mit demselben Verhalten umzuwandeln. Es gibt derzeit keine benutzerdefinierte Syntaxunterstützung für RxJS in normalem JavaScript. Dennoch ist es eine interessante Lösung für die Herausforderungen, mit denen RxJS konfrontiert ist.
Mit dem Gesagten: Was sind eure Gedanken zu diesem Thema? Was tut ihr, um die RxJS-Ketten lesbar zu halten? Schreibt es in den Kommentar unten.
Agent Hub
Gehen Sie über vereinzelte AI-Piloten hinaus und schaffen Sie eine sichere, skalierbare Grundlage für Agentic AI in Ihrer gesamten Organisation.
Zur Demo




