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

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


1. 短轮询(Short Polling)

原理
客户端通过 定时器(如每 5 秒) 主动向服务器发送请求,无论数据是否有更新。
特点
• ✅ 实现简单,兼容所有 HTTP 服务
• ❌ 频繁无效请求,资源浪费严重
• ❌ 实时性差(依赖轮询间隔)

适用场景:静态数据低频更新(如天气预报、配置拉取)。

// 短轮询代码(Axios)
let isPollingActive = true;

const startShortPolling = async () => {
    
    
  while (isPollingActive) {
    
    
    try {
    
    
      const response = await axios.get('/api/short-poll');
      console.log('短轮询数据:', response.data);
      await new Promise(resolve => setTimeout(resolve, 5000)); // 5秒间隔
    } catch (error) {
    
    
      console.error('短轮询失败:', error);
      isPollingActive = false; // 出错时停止
    }
  }
};

// 启动轮询
startShortPolling();

// 停止轮询
const stopShortPolling = () => {
    
    
  isPollingActive = false;
};

2. 长轮询(Long Polling)

原理
客户端发送请求后,服务器会 挂起连接直到数据更新或超时(如 30 秒)。客户端收到响应后立即重新发起请求。
特点
• ✅ 减少无效请求,实时性优于短轮询
• ❌ 需要服务器支持长时挂起
• ❌ 客户端需处理超时和重连

适用场景:实时聊天、订单状态跟踪等中等实时性需求。

// 长轮询代码(Axios + AbortController)
const abortController = new AbortController();

const startLongPolling = async () => {
    
    
  try {
    
    
    const response = await axios.get('/api/long-poll', {
    
    
      signal: abortController.signal, // 绑定中断控制器
      timeout: 30000 // 30秒超时
    });
    console.log('长轮询数据:', response.data);
    startLongPolling(); // 立即发起下一次请求
  } catch (error) {
    
    
    if (axios.isCancel(error)) {
    
    
      console.log('长轮询被手动终止');
    } else {
    
    
      console.error('长轮询错误:', error);
      setTimeout(startLongPolling, 1000); // 1秒后重试
    }
  }
};

// 启动长轮询
startLongPolling();

// 终止长轮询
const stopLongPolling = () => {
    
    
  abortController.abort();
};

3. 长连接(Long Connection)

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

3.1 WebSocket(双向通信)
// 浏览器原生 API(Axios 不适用)
const socket = new WebSocket('wss://your-websocket-server');

socket.addEventListener('open', () => {
    
    
  socket.send('连接已建立');
});

socket.addEventListener('message', (event) => {
    
    
  console.log('收到消息:', event.data);
});
3.2 SSE(单向推送)
// 浏览器原生 API(Axios 不适用)
const eventSource = new EventSource('/api/sse');

eventSource.onmessage = (event) => {
    
    
  console.log('SSE 数据:', event.data);
};

eventSource.onerror = () => {
    
    
  console.error('SSE 连接异常');
};

对比总结

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

实际开发建议

  1. 短轮询
    • 使用 setTimeoutsetInterval 控制频率
    • 添加请求锁(如 isPollingActive)避免并发冲突

  2. 长轮询
    • 使用 AbortController 精准控制请求中断
    • 添加重试机制(如指数退避 setTimeout(retry, 1000 * 2^attempt)

  3. 长连接
    • 高频双向通信选 WebSocket(如在线游戏)
    • 单向推送选 SSE(如新闻实时播报)
    • 使用 Socket.io 库简化 WebSocket 开发

// 长轮询重试逻辑示例(指数退避)
let retryCount = 0;
const MAX_RETRIES = 5;

const fetchWithRetry = async () => {
    
    
  try {
    
    
    const response = await axios.get('/api/data');
    retryCount = 0; // 重置重试计数器
    return response.data;
  } catch (error) {
    
    
    if (retryCount < MAX_RETRIES) {
    
    
      retryCount++;
      await new Promise(resolve => 
        setTimeout(resolve, 1000 * Math.pow(2, retryCount))
      );
      return fetchWithRetry();
    } else {
    
    
      throw new Error('超过最大重试次数');
    }
  }
};

注意事项

服务端适配:长轮询需服务器支持挂起请求(如 Node.js 的 keep-alive
性能监控:短轮询频繁请求可能触发服务器限流
浏览器兼容性:SSE 不支持 IE,WebSocket 需现代浏览器

猜你喜欢

转载自blog.csdn.net/m0_55049655/article/details/146996230
今日推荐