El problema: HTTP no avisa
HTTP es petición → respuesta: el cliente pregunta y el servidor contesta. El servidor no puede hablar primero. Para un chat eso es un problema: si otra persona escribe, ¿cómo te enteras?
La solución ingenua es el polling: preguntar cada pocos segundos "¿hay algo nuevo?".
setInterval(async () => {
const nuevos = await fetch("/mensajes?desde=" + ultimoId);
// ...
}, 2000);
El polling funciona, pero es malo para el tiempo real:
- Latencia: un mensaje puede tardar hasta el intervalo completo en aparecer.
- Desperdicio: la mayoría de peticiones vuelven vacías; cada una abre una conexión, manda cabeceras, etc.
- No escala: miles de clientes preguntando cada 2 s saturan el servidor.
La solución: WebSockets
Un WebSocket abre una sola conexión persistente y bidireccional. Tras un handshake sobre HTTP, el canal queda abierto y cualquiera de los dos lados puede enviar datos cuando quiera, sin volver a pedir permiso.
| HTTP / polling | WebSocket | |
|---|---|---|
| Dirección | cliente pregunta | bidireccional |
| Conexión | una por petición | una persistente |
| Latencia | hasta el intervalo | inmediata (push) |
| ¿Servidor inicia? | no | sí |
Socket.io es una librería muy usada que se apoya en WebSockets (con fallbacks) y añade reconexión, salas y eventos con nombre. En este proyecto el transporte (el WebSocket real) es conceptual —no corre en el sandbox del navegador— pero la lógica que vive encima (pub/sub, salas, presencia) la vas a implementar y validar de verdad.
Ejemplos
Polling: simple pero con latencia y desperdicio
let ultimo = 0;
const cola = [{ id: 1, txt: "hola" }]; // simula el servidor
function poll() {
const nuevos = cola.filter((m) => m.id > ultimo);
if (nuevos.length) ultimo = nuevos[nuevos.length - 1].id;
console.log("recibidos:", nuevos.length);
}
poll();
poll(); // la segunda vez ya no hay nada nuevo