Quando um site "vivo" exige código vivo
\nImagine: você está escrevendo um mensageiro em TypeScript. O usuário envia uma mensagem — e o interlocutor deve vê-la instantaneamente, sem recarregar a página. Ou um painel de ações, onde o preço das ações muda a cada segundo. Ou simplesmente um feed de notificações que se atualiza sozinho. Como implementar isso? Dois principais candidatos — long polling e WebSocket. Mas qual escolher para não prejudicar o desempenho e não quebrar a UX?
\nNeste artigo, com exemplos reais em TypeScript, analisaremos como cada tecnologia funciona, onde brilham e onde falham. Você receberá não apenas teoria, mas também trechos de código prontos para Node.js e navegador. Vamos lá!
\n\nO que é Long Polling em TypeScript e como funciona
\nLong polling é uma evolução da requisição HTTP comum. O cliente envia uma requisição ao servidor, mas o servidor não responde imediatamente se não houver dados. Ele mantém a conexão aberta até que um novo evento ocorra. Assim que os dados estão prontos — o servidor envia a resposta, o cliente a processa e imediatamente cria uma nova requisição. O ciclo se repete.
\nParece um improviso? Em parte, sim. Mas funciona mesmo através dos proxies corporativos mais restritivos, que bloqueiam WebSocket.
\n\nImplementação de Long Polling em TypeScript (parte do servidor)
\nVamos escrever um servidor simples com Express e TypeScript. Ele irá emular uma fila de mensagens.
\nimport express, { Request, Response } from 'express';\nimport cors from 'cors';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\n\n// Armazenamento de mensagens (simulação de fila)\nconst messages: string[] = [];\n\n// Endpoint para long polling\napp.get('/poll', (req: Request, res: Response) => {\n // Aguarda nova mensagem por até 30 segundos\n const checkForMessage = () => {\n if (messages.length > 0) {\n // Envia a primeira mensagem e a remove da fila\n const message = messages.shift();\n res.json({ data: message, timestamp: Date.now() });\n } else {\n // Se não houver mensagens — continua aguardando\n setTimeout(checkForMessage, 1000); // verifica a cada segundo\n }\n };\n\n // Timeout caso não haja mensagens por muito tempo\n const timeout = setTimeout(() => {\n res.json({ data: null, timeout: true });\n }, 30000);\n\n // Se o cliente desconectar — limpa os timers\n req.on('close', () => {\n clearTimeout(timeout);\n });\n\n checkForMessage();\n});\n\n// Endpoint para enviar mensagem\napp.post('/send', (req: Request, res: Response) => {\n const { message } = req.body;\n if (message) {\n messages.push(message);\n res.status(200).json({ status: 'ok' });\n } else {\n res.status(400).json({ error: 'message is required' });\n }\n});\n\napp.listen(3000, () => console.log('Long poll server on port 3000'));\n\nParte do cliente em TypeScript (navegador)
\nasync function startLongPolling() {\n try {\n const response = await fetch('http://localhost:3000/poll');\n const data = await response.json();\n\n if (data.data) {\n console.log('Nova mensagem:', data.data);\n // Atualiza a UI\n updateUI(data.data);\n }\n\n // Inicia imediatamente um novo poll\n startLongPolling();\n } catch (error) {\n console.error('Erro no long polling:', error);\n // Aguarda 2 segundos e tenta novamente\n setTimeout(startLongPolling, 2000);\n }\n}\n\nfunction updateUI(message: string) {\n // Seu código para atualizar o DOM\n const container = document.getElementById('messages');\n if (container) {\n const item = document.createElement('li');\n item.textContent = message;\n container.appendChild(item);\n }\n}\n\n// Inicia ao carregar a página\ndocument.addEventListener('DOMContentLoaded', startLongPolling);\nConclusão: long polling é simples de implementar e não requer protocolos especiais. Mas cada requisição envolve cabeçalhos HTTP, cookies, overhead. Com 1000 clientes simultâneos