Ihre letzte Lösung ist die einzig richtige.
Die beiden anderen Lösungen sollten nicht so funktionieren, wie Sie es erwartet haben. Eigentlich sollte dies zu einer Endlosschleife führen.
Dies liegt daran, wie der Eventloop von JavaScript funktioniert. Das folgende Bild zeigt ein Modell der JavaScript-Laufzeit (Bild wurde von hier aufgenommen ):
Die für uns relevanten Teile sind die stack
und die queue
. Eine JavaScript-Laufzeit verarbeitet die Nachrichten auf dem queue
. Jede Nachricht ist einer Funktion zugeordnet, die beim Verarbeiten der Nachricht aufgerufen wird.
Für den Stapel erstellt jeder Funktionsaufruf einen Rahmen auf dem Stapel, der die Funktionsargumente und lokalen Variablen enthält. Wenn eine Funktion eine andere Funktion aufruft, wird ein neuer Frame auf den Stapel geschoben. Wenn eine Funktion zurückkehrt, wird der obere Frame aus dem Stapel entfernt.
Wenn der Stapel leer ist, verarbeitet die JavaScript-Laufzeit die nächste Nachricht auf der queue
(ältesten).
Wenn Sie verwenden setTimeout(() => doSomething(),100)
, wird die doSomething()
Funktion nach 100 Millisekunden zur Warteschlange hinzugefügt. Dies ist der Grund, warum die 100 Millisekunden keine garantierte Zeit, sondern eine minimale Zeit sind. Daher wird Ihr doSomething method
nur aufgerufen, wenn der Stapel leer ist und sich nichts anderes in der Warteschlange befindet.
Da Sie jedoch in einer while-Schleife iterieren und Ihr Zustand vom Code in Ihrer Schleife abhängt setTimeout
, haben Sie eine Endlosschleife erstellt, da der Stapel nicht leer wird und Ihr this.posts.push(this.postService.next(10));
Code daher niemals aufgerufen wird.
Für die RxJS-Implementierungen gilt das Gleiche. Sie verwenden Scheduler, um das Timing zu handhaben. Es gibt verschiedene interne Scheduler-Implementierungen in RxJS, aber wie wir in den Implementierungen für interval
und sehen können timer
, ist die Standardeinstellung der asyncScheduler, wenn wir keinen Scheduler angeben. Die asyncScheduler-Zeitpläne setInterval
funktionieren wie setTimeout
oben beschrieben und senden eine weitere Nachricht in die Warteschlange.
Ich habe Ihre beiden Lösungen mit der while-Schleife ausprobiert und tatsächlich hat die erste meinen Browser völlig eingefroren, während die zweite sehr verzögert war, aber innerhalb der while-Schleife etwas an die Konsole ausgeben konnte. Ich weiß eigentlich nicht, warum der zweite etwas performanter ist, aber trotzdem sind beide nicht das, was Sie eigentlich wollen. Sie haben bereits eine gute Lösung gefunden, und ich hoffe, diese Antwort hilft Ihnen zu verstehen, warum die ersten Lösungen so schlecht funktionieren.