Sua última solução é a única correta.
As outras duas soluções não devem funcionar como você esperava que funcionassem. Na verdade, isso deve resultar em um loop infinito.
Isso ocorre porque o eventloop do JavaScript funciona. A figura a seguir mostra um modelo do tempo de execução JavaScript (a imagem foi tirada daqui ):
As partes relevantes para nós são o stack
e o queue
. Um tempo de execução JavaScript processa as mensagens no queue
. Cada mensagem é associada a uma função que é chamada à medida que a mensagem é processada.
Para a pilha, cada chamada de função cria um quadro na pilha que contém os argumentos das funções e variáveis locais. Se uma função chama outra função, um novo quadro é empurrado para cima da pilha. Quando uma função retorna, o quadro superior é retirado da pilha.
Agora, se a pilha estiver vazia, o tempo de execução do JavaScript processará a próxima mensagem na queue
(a mais antiga).
Se você usar setTimeout(() => doSomething(),100)
, a doSomething()
função será adicionada à fila após 100 milissegundos. Esta é a razão pela qual os 100 milissegundos não são um tempo garantido, mas um tempo mínimo. Portanto, você doSomething method
só é chamado se a pilha estiver vazia e não houver mais nada na fila.
Mas como você está iterando em um loop while e sua condição depende do código dentro do seu setTimeout
, você criou um loop infinito porque a pilha não fica vazia e, portanto, seu this.posts.push(this.postService.next(10));
código nunca será chamado.
Para as implementações do RxJS, o mesmo é verdadeiro. Eles usam agendadores para lidar com o tempo. Existem diferentes implementações do agendador interno no RxJS, mas como podemos ver nas implementações de interval
e timer
, se não especificarmos um agendador, o padrão é o asyncScheduler. Os agendamentos asyncScheduler funcionam com os setInterval
quais funcionam como setTimeout
mencionado acima e enviam outra mensagem à fila.
Eu tentei suas duas soluções com o loop while e, na verdade, a primeira congelou totalmente meu navegador enquanto a segunda estava super atrasada, mas poderia gerar algo para o console dentro do loop while. Na verdade, não sei por que o segundo é um pouco mais eficiente, mas, no entanto, ambos não são o que você realmente deseja. Você já encontrou uma boa solução e espero que esta resposta possa ajudá-lo a entender por que as primeiras soluções são tão ruins.