TypeScript中的Long Polling与WebSocket:实时通信该如何选择?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

当“动态”网站需要实时代码

\n

想象一下:您正在用TypeScript编写一个即时通讯应用。用户发送一条消息——对方必须立即看到它,无需刷新页面。或者一个股票仪表盘,股价每秒都在变化。又或者一个自动更新的通知列表。如何实现这些功能?两个主要候选方案是long polling和WebSocket。但该如何选择,才能既不影响性能,又不破坏用户体验?

\n

在本文中,我们将通过TypeScript的实际示例,深入分析每种技术的工作原理、优势所在以及潜在缺陷。您不仅能学到理论知识,还能获得适用于Node.js和浏览器的现成代码片段。让我们开始吧!

\n\n

TypeScript中的Long Polling是什么,它是如何工作的

\n

Long polling是普通HTTP请求的一种演进形式。客户端向服务器发送请求,但如果服务器没有数据,它不会立即响应。服务器会保持连接打开,直到有新事件发生。一旦数据准备就绪——服务器发送响应,客户端处理该响应,并立即发起新的请求。如此循环往复。

\n

听起来像是一种权宜之计?某种程度上确实如此。但即使是最严格的企业代理(会阻止WebSocket)也能支持这种方案。

\n\n

在TypeScript中实现Long Polling(服务器端)

\n

让我们用Express和TypeScript编写一个简单的服务器。它将模拟一个消息队列。

\n
import 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\n

TypeScript客户端(浏览器端)

\n
async 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个并发客户端时

博客

书籍推荐