Votre dernière solution est la seule correcte.
Les deux autres solutions ne devraient pas fonctionner comme vous vous attendiez à ce qu'elles fonctionnent. En fait, cela devrait entraîner une boucle infinie.
Cela est dû au fonctionnement de la boucle d' événements JavaScript . L'image suivante montre un modèle du runtime JavaScript (l'image a été prise à partir d' ici ):
Les parties pertinentes pour nous sont le stack
et le queue
. Un runtime JavaScript traite les messages sur le queue
. Chaque message est associé à une fonction qui est appelée lors du traitement du message.
Pour la pile, chaque appel de fonction crée un cadre sur la pile qui contient les arguments des fonctions et les variables locales. Si une fonction appelle une autre fonction, un nouveau cadre est poussé au-dessus de la pile. Lorsqu'une fonction revient, le cadre supérieur est sorti de la pile.
Maintenant, si la pile est vide, le runtime JavaScript traitera le message suivant sur le queue
(le plus ancien).
Si vous utilisez setTimeout(() => doSomething(),100)
, la doSomething()
fonction est ajoutée à la file d'attente après 100 millisecondes. C'est la raison pour laquelle les 100 millisecondes ne sont pas un temps garanti mais un temps minimal. Par conséquent, votre doSomething method
seul est appelé, si la pile est vide et que rien d'autre n'est dans la file d'attente.
Mais comme vous itérez dans une boucle while et que votre condition dépend du code à l'intérieur de votre setTimeout
, vous avez créé une boucle infinie car la pile ne sera pas vide et donc votre this.posts.push(this.postService.next(10));
code ne sera jamais appelé.
Pour les implémentations RxJS, la même chose est vraie. Ils utilisent des planificateurs pour gérer le timing. Il existe différentes implémentations de planificateur interne dans RxJS, mais comme nous pouvons le voir dans les implémentations de interval
et timer
, si nous ne spécifions pas de planificateur, la valeur par défaut est asyncScheduler. Les planifications asyncScheduler fonctionnent avec setInterval
ce qui fonctionne comme setTimeout
mentionné ci-dessus et poussent un autre message dans la file d'attente.
J'ai essayé vos deux solutions avec la boucle while et en fait la première a complètement gelé mon navigateur tandis que la seconde était super laggy mais pouvait sortir quelque chose vers la console à l'intérieur de la boucle while. En fait, je ne sais pas pourquoi le second est un peu plus performant, mais néanmoins les deux ne sont pas ce que vous voulez réellement. Vous avez déjà trouvé une bonne solution et j'espère que cette réponse vous aidera à comprendre pourquoi les premières solutions fonctionnent si mal.