短轮询、长轮询与长连接详解及 Axios、SSE、WS 代码实现 ...

打印 上一主题 下一主题

主题 1802|帖子 1802|积分 5406

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
短轮询、长轮询与长连接详解及 Axios 代码实现


1. 短轮询(Short Polling)

原理
客户端通过 定时器(如每 5 秒) 主动向服务器发送请求,无论数据是否有更新。
特点
• ✅ 实现简单,兼容所有 HTTP 服务
• ❌ 频繁无效请求,资源浪费严重
• ❌ 实时性差(依靠轮询间隔)
适用场景:静态数据低频更新(如气候预报、设置拉取)。
  1. // 短轮询代码(Axios)
  2. let isPollingActive = true;
  3. const startShortPolling = async () => {
  4.   while (isPollingActive) {
  5.     try {
  6.       const response = await axios.get('/api/short-poll');
  7.       console.log('短轮询数据:', response.data);
  8.       await new Promise(resolve => setTimeout(resolve, 5000)); // 5秒间隔
  9.     } catch (error) {
  10.       console.error('短轮询失败:', error);
  11.       isPollingActive = false; // 出错时停止
  12.     }
  13.   }
  14. };
  15. // 启动轮询
  16. startShortPolling();
  17. // 停止轮询
  18. const stopShortPolling = () => {
  19.   isPollingActive = false;
  20. };
复制代码

2. 长轮询(Long Polling)

原理
客户端发送请求后,服务器会 挂起连接直到数据更新或超时(如 30 秒)。客户端收到响应后立即重新发起请求。
特点
• ✅ 减少无效请求,实时性优于短轮询
• ❌ 需要服务器支持长时挂起
• ❌ 客户端需处置惩罚超时和重连
适用场景:实时谈天、订单状态跟踪等中等实时性需求。
  1. // 长轮询代码(Axios + AbortController)
  2. const abortController = new AbortController();
  3. const startLongPolling = async () => {
  4.   try {
  5.     const response = await axios.get('/api/long-poll', {
  6.       signal: abortController.signal, // 绑定中断控制器
  7.       timeout: 30000 // 30秒超时
  8.     });
  9.     console.log('长轮询数据:', response.data);
  10.     startLongPolling(); // 立即发起下一次请求
  11.   } catch (error) {
  12.     if (axios.isCancel(error)) {
  13.       console.log('长轮询被手动终止');
  14.     } else {
  15.       console.error('长轮询错误:', error);
  16.       setTimeout(startLongPolling, 1000); // 1秒后重试
  17.     }
  18.   }
  19. };
  20. // 启动长轮询
  21. startLongPolling();
  22. // 终止长轮询
  23. const stopLongPolling = () => {
  24.   abortController.abort();
  25. };
复制代码

3. 长连接(Long Connection)

原理
基于 WebSocket(双向通信)SSE(Server-Sent Events,单向推送) 的持久连接,服务器可主动推送数据。
特点
• ✅ 实时性最高,无频繁请求开销
• ❌ 需要协媾和服务器支持(如 WebSocket 需 ws://)
• ❌ 实现复杂度较高
3.1 WebSocket(双向通信)

  1. // 浏览器原生 API(Axios 不适用)
  2. const socket = new WebSocket('wss://your-websocket-server');
  3. socket.addEventListener('open', () => {
  4.   socket.send('连接已建立');
  5. });
  6. socket.addEventListener('message', (event) => {
  7.   console.log('收到消息:', event.data);
  8. });
复制代码
3.2 SSE(单向推送)

  1. // 浏览器原生 API(Axios 不适用)
  2. const eventSource = new EventSource('/api/sse');
  3. eventSource.onmessage = (event) => {
  4.   console.log('SSE 数据:', event.data);
  5. };
  6. eventSource.onerror = () => {
  7.   console.error('SSE 连接异常');
  8. };
复制代码

对比总结

方式实时性资源斲丧实现复杂度协议依靠短轮询低高(频繁请求)简单HTTP 1.1+长轮询中中(减少请求)中等需服务器支持挂起WebSocket高低(持久连接)复杂WebSocket 协议SSE高低(单向推送)中等HTTP/2+
实际开发发起


  • 短轮询
    • 利用 setTimeout 或 setInterval 控制频率
    • 添加请求锁(如 isPollingActive)避免并发冲突
  • 长轮询
    • 利用 AbortController 精准控制请求中断
    • 添加重试机制(如指数退避 setTimeout(retry, 1000 * 2^attempt))
  • 长连接
    • 高频双向通信选 WebSocket(如在线游戏)
    • 单向推送选 SSE(如新闻实时播报)
    • 利用 Socket.io 库简化 WebSocket 开发
  1. // 长轮询重试逻辑示例(指数退避)
  2. let retryCount = 0;
  3. const MAX_RETRIES = 5;
  4. const fetchWithRetry = async () => {
  5.   try {
  6.     const response = await axios.get('/api/data');
  7.     retryCount = 0; // 重置重试计数器
  8.     return response.data;
  9.   } catch (error) {
  10.     if (retryCount < MAX_RETRIES) {
  11.       retryCount++;
  12.       await new Promise(resolve =>
  13.         setTimeout(resolve, 1000 * Math.pow(2, retryCount))
  14.       );
  15.       return fetchWithRetry();
  16.     } else {
  17.       throw new Error('超过最大重试次数');
  18.     }
  19.   }
  20. };
复制代码

注意事项

服务端适配:长轮询需服务器支持挂起请求(如 Node.js 的 keep-alive)
性能监控:短轮询频繁请求大概触发服务器限流
欣赏器兼容性:SSE 不支持 IE,WebSocket 需今世欣赏器

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

伤心客

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表