当“动态”网站需要实时代码
\n想象一下:您正在用TypeScript编写一个即时通讯应用。用户发送一条消息——对方必须立即看到它,无需刷新页面。或者一个股票仪表盘,股价每秒都在变化。又或者一个自动更新的通知列表。如何实现这些功能?两个主要候选方案是long polling和WebSocket。但该如何选择,才能既不影响性能,又不破坏用户体验?
\n在本文中,我们将通过TypeScript的实际示例,深入分析每种技术的工作原理、优势所在以及潜在缺陷。您不仅能学到理论知识,还能获得适用于Node.js和浏览器的现成代码片段。让我们开始吧!
\n\nTypeScript中的Long Polling是什么,它是如何工作的
\nLong polling是普通HTTP请求的一种演进形式。客户端向服务器发送请求,但如果服务器没有数据,它不会立即响应。服务器会保持连接打开,直到有新事件发生。一旦数据准备就绪——服务器发送响应,客户端处理该响应,并立即发起新的请求。如此循环往复。
\n听起来像是一种权宜之计?某种程度上确实如此。但即使是最严格的企业代理(会阻止WebSocket)也能支持这种方案。
\n\n在TypeScript中实现Long Polling(服务器端)
\n让我们用Express和TypeScript编写一个简单的服务器。它将模拟一个消息队列。
\nimport express, { Request, Response } from 'express';\nimport cors from 'cors';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\n\n// 消息存储(模拟队列)\nconst messages: string[] = [];\n\n// Long polling端点\napp.get('/poll', (req: Request, res: Response) => {\n // 等待新消息,最多30秒\n const checkForMessage = () => {\n if (messages.length > 0) {\n // 发送第一条消息并将其从队列中移除\n const message = messages.shift();\n res.json({ data: message, timestamp: Date.now() });\n } else {\n // 如果没有消息——继续等待\n setTimeout(checkForMessage, 1000); // 每秒检查一次\n }\n };\n\n // 长时间没有消息时的超时处理\n const timeout = setTimeout(() => {\n res.json({ data: null, timeout: true });\n }, 30000);\n\n // 如果客户端断开连接——清理定时器\n req.on('close', () => {\n clearTimeout(timeout);\n });\n\n checkForMessage();\n});\n\n// 发送消息的端点\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\nTypeScript客户端(浏览器端)
\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('新消息:', data.data);\n // 更新UI\n updateUI(data.data);\n }\n\n // 立即启动新的轮询\n startLongPolling();\n } catch (error) {\n console.error('Long polling错误:', error);\n // 等待2秒后重试\n setTimeout(startLongPolling, 2000);\n }\n}\n\nfunction updateUI(message: string) {\n // 您的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// 页面加载时启动\ndocument.addEventListener('DOMContentLoaded', startLongPolling);\n总结: long polling实现简单,不需要特殊协议。但每个请求都包含HTTP头部、cookie等开销。当有1000个并发客户端时