O problema: o HTTP não avisa
O HTTP é requisição → resposta: o cliente pergunta e o servidor responde. O servidor não pode falar primeiro. Para um chat isso é um problema: se outra pessoa escreve, como você fica sabendo?
A solução ingênua é o polling: perguntar a cada poucos segundos "tem algo novo?".
setInterval(async () => {
const novos = await fetch("/mensagens?desde=" + ultimoId);
// ...
}, 2000);
O polling funciona, mas é ruim para o tempo real:
- Latência: uma mensagem pode demorar até o intervalo inteiro para aparecer.
- Desperdício: a maioria das requisições volta vazia; cada uma abre uma conexão, envia cabeçalhos, etc.
- Não escala: milhares de clientes perguntando a cada 2 s saturam o servidor.
A solução: WebSockets
Um WebSocket abre uma única conexão persistente e bidirecional. Após um handshake sobre HTTP, o canal fica aberto e qualquer um dos dois lados pode enviar dados quando quiser, sem pedir permissão de novo.
| HTTP / polling | WebSocket | |
|---|---|---|
| Direção | cliente pergunta | bidirecional |
| Conexão | uma por requisição | uma persistente |
| Latência | até o intervalo | imediata (push) |
| Servidor inicia? | não | sim |
O Socket.io é uma biblioteca muito usada que se apoia em WebSockets (com fallbacks) e adiciona reconexão, salas e eventos com nome. Neste projeto o transporte (o WebSocket real) é conceitual —não roda no sandbox do navegador— mas a lógica que vive em cima (pub/sub, salas, presença) você vai implementar e validar de verdade.
Exemplos
Polling: simples mas com latência e desperdício
let ultimo = 0;
const fila = [{ id: 1, txt: "oi" }]; // simula o servidor
function poll() {
const novos = fila.filter((m) => m.id > ultimo);
if (novos.length) ultimo = novos[novos.length - 1].id;
console.log("recebidos:", novos.length);
}
poll();
poll(); // na segunda vez já não há nada novo