O negócio é entender a diferença entre cooperative multitasking e preemptive multitasking. No primeiro, os diversos "atores" precisam cooperar entre si. Isso significa ser um bom cidadão e não tomar todo o "tempo de CPU" para si—periodicamente, você precisa "ceder" o controle.
Há um tempo eu fiz um post mostrando que sua operação sincrona ia travar tua API Node. Esse é um post mais DEEP sobre esse tema. Sobre o termo "EventLoop Travar": O V8 executa os frames de funções referenciadas na CallStack. Enquanto houver pelo menos um frame ativo na CallStack, o V8 vai estar torando código síncrono e o EventLoop vai ficar afk. Ele só move essas callback pra CallStack quando a mesma está vazia. Dependendo da função assíncrona que lida com essa callback ela pode ir pra uma fila diferente: ex: setTimeout callback → Macrotask Promise callback → Microtask Existe uma prioridade entre essas filas: Microtasks tem prioridade total sobre Macrotasks. O Event Loop sempre processa TODAS as Microtasks disponiveis antes de pegar uma unica Macrotask. ex: Promises executam antes de setTimeout(fn, 0). Mas quando essas callbacks vão pra MicrotaskQueue? No caso das Promises, quando o status muda de pending pra resolved/rejected. Aí tudo que está dentro do seu .then(callback) ou abaixo do seu await (callbacks via sugar syntax) vai direto pra Microtask Queue. Enfim: Enquanto o V8 está torando a CallStack processando seu código síncrono JIT (Just in Time) a callback do seu .then nunca vai ser executada. Ou aquele codigo que vem abaixo do seu await. E por tal motivo sua API vai parar de responder geral e seu sistema continuará bronze V.

Oct 31, 2025 · 9:18 PM UTC

1
3
6
Essa cessão muitas vezes é feita com um await, um callback, etc. Quando você tem um loop infinito (ou qualquer outra operação "bloqueante", o seu "ator" não irá ceder o controle para nenhum outro, o que pode interromper as outras partes do sistema de progredirem.
1
3
Por outro lado, em multitasking preemptivo (como o próprio sistema operacional, o runtime de Golang, etc), você não precisa se preocupar tanto com isso. Um ator "egoísta" que não cede o controle para os demais vai sempre ser periodicamente interrompido pelo scheduler.
1
1
3
Por isso que em Go, mesmo sem await ou callbacks, as suas várias gorrotinas conseguem fazer progresso mutuamente. Ou os diversos processos do sistema, que podem estar com while (true), não vão te impedir de usar o resto do computador.
1
3
Ótimo post sobre esse assunto, btw: os.phil-opp.com/async-await/
1
1
4
Inclusive uma pergunta interessante que dá para tirar disso é por que, de modo geral, linguagens de programação podem se dar ao luxo de usarem runtimes cooperativos, mas sistemas operacionais (a não ser alguns muito nichados) *precisam* ser preemptivos?
1
1
4