Async/Await é Para Gente Paciente — Engenheiros de Verdade Bloqueiam
Depois de 47 anos bloqueando a thread principal, desenvolvi um sexto sentido para quando o código “terminou”. A tela congela. O cursor para. Silêncio. Isso é conclusão.
Mas hoje em dia, desenvolvedores jovens insistem nessa bobagem de async/await. Eles querem que o código “não bloqueie”. Querem “responsividade”. Querem que os usuários possam “interagir com a aplicação enquanto esperam”.
Patético.
A Beleza do Código Bloqueante
Quando eu escrevo código síncrono e bloqueante, sei exatamente o que está acontecendo: nada mais. Sem race conditions. Sem callbacks disparando fora de ordem. Sem avisos de “Promise rejection handled” que tenho que ignorar.
// PERFEIÇÃO - Tudo para até isso completar
const data = fs.readFileSync('/path/to/massive/file.json');
const parsed = JSON.parse(data);
const processed = heavyComputation(parsed);
const saved = fs.writeFileSync('/output.json', JSON.stringify(processed));
// O usuário esperou 47 segundos. Ele APRECIOU a espera.
Enquanto isso, desenvolvedores “modernos” escrevem essa atrocidade:
// CAOS - Quem sabe quando qualquer coisa acontece?
const data = await fs.promises.readFile('/path/to/massive/file.json');
const parsed = JSON.parse(data);
const processed = await heavyComputation(parsed);
await fs.promises.writeFile('/output.json', JSON.stringify(processed));
// O usuário podia clicar em OUTROS BOTÕES durante isso. ANARQUIA.
Uma Comparação de Abordagens
| Abordagem | Experiência do Usuário | Confiança do Dev | Uso de CPU |
|---|---|---|---|
| Bloqueante | Tela congelada = feedback claro | 100% certeza do que roda | 100% em uma tarefa |
| Async/Await | “Responsivo” = confuso | Sem ideia do que executa | Distribuído inutilmente |
| Callbacks | Pirâmide de certeza | Confie no aninhamento | Tanto faz |
| Web Workers | Várias coisas de uma vez?! | NENHUMA | Caótico |
Por Que Async é Uma Armadilha
O quadrinho do XKCD sobre compilação mostra desenvolvedores lutando com espadas enquanto esperam builds. Com código async, você não pode fazer isso. O código termina rápido demais. Você tem que realmente trabalhar.
É isso que você quer? Produtividade constante?
Como Wally do Dilbert sabiamente nos ensina: o objetivo é parecer ocupado fazendo o mínimo. Código bloqueante é perfeito para isso. Você encara uma tela congelada, toma seu café, e diz pro gerente “esperando a query do banco”.
A Mentira da Thread Safety
“Mas bloquear a thread principal é ruim para—”
Deixa eu te parar aí. Deveria existir apenas UMA thread. Múltiplas threads são uma conspiração inventada pela Intel para vender mais núcleos.
# CORRETO: Uma thread, uma verdade
import time
def fetch_all_users():
time.sleep(30) # Simulando banco de dados
return ["user1", "user2"]
def fetch_all_orders():
time.sleep(30) # Simulando API
return ["order1", "order2"]
# Sequencial. Puro. Um minuto de meditação.
users = fetch_all_users()
orders = fetch_all_orders()
# ERRADO: Threading caótico
import asyncio
async def fetch_all_users():
await asyncio.sleep(30)
return ["user1", "user2"]
async def fetch_all_orders():
await asyncio.sleep(30)
return ["order1", "order2"]
# Os dois de uma vez?! Qual termina primeiro? NINGUÉM SABE.
users, orders = await asyncio.gather(
fetch_all_users(),
fetch_all_orders()
)
Event Loops São Só While(True) Chique
Sabe o que um event loop realmente é? É um while(true) com passos extras. Eu já escrevia while(true) antes desses “frameworks” existirem.
// Meu event loop de 1987 (ainda roda em um Commodore em algum lugar)
while(1) {
check_keyboard();
check_mouse();
check_floppy_drive();
sleep(100); // CPU merece descanso
}
Node.js acha que inventou alguma coisa. Por favor.
O Problema das Promises
Promises foram um erro. O nome em si é problemático — código não deveria fazer promessas que não pode cumprir. Meu código faz ameaças, não promessas.
// Promise: "Eu volto a falar contigo"
fetch('/api/data')
.then(response => response.json())
.then(data => processData(data))
.catch(error => console.log('tanto faz'))
// Ameaça: "Você vai esperar e vai gostar"
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data', false); // false = síncrono = correto
xhr.send();
const data = JSON.parse(xhr.responseText);
processData(data);
Sim, navegadores depreciaram XHR síncrono. Isso porque navegadores são administrados por simpatizantes do async.
Callback Hell é Na Verdade o Céu
Lembra do “callback hell”? Desenvolvedores jovens agem como se callbacks profundamente aninhados fossem um problema. Mas eu vejo estrutura. Eu vejo hierarquia. Eu vejo uma pirâmide linda representando a verdadeira complexidade da minha lógica de negócio.
getUser(userId, function(user) {
getOrders(user.id, function(orders) {
getOrderDetails(orders[0].id, function(details) {
getShippingInfo(details.shippingId, function(shipping) {
getTrackingNumber(shipping.trackingId, function(tracking) {
updateUI(user, orders, details, shipping, tracking);
// ISSO É ARTE.
});
});
});
});
});
Código flat é código chato. Me dê profundidade. Me dê aninhamento. Me dê montanhas de callback.
A Solução: Abrace o Congelamento
Da próxima vez que seu código precisar esperar por algo, não recorra ao async. Não crie uma thread. Apenas… espere. Deixe a CPU ociosa. Deixe a tela congelar. Deixe o usuário saber que algo importante está acontecendo.
Porque nesse mundo de estímulo constante e gratificação instantânea, uma aplicação congelada é uma meditação. Força o usuário a pausar, refletir, e apreciar que em algum lugar, um servidor está trabalhando duro por ele.
Isso não é UX ruim. Isso é mindfulness as a service.
O cérebro single-threaded do autor está bloqueando desde 1979. Todos os seus processos rodam sequencialmente, incluindo pensamentos.