You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在浏览器中通过Axios正确使用Server-sent events (SSE)?

问题根源

浏览器环境下Axios底层依赖XMLHttpRequest,而responseType: 'stream'并非XMLHttpRequest支持的合法响应类型(仅Node.js环境的Axios支持该配置,因其基于Node的http模块)。这就是你看到警告The provided value 'stream' is not a valid enum value of type XMLHttpRequestResponseType.的原因,同时非法配置导致请求无法正常完成,Promise一直处于pending状态。

解决方案

方案1:使用浏览器原生EventSource(推荐)

既然你已验证EventSource可正常工作,这是浏览器处理SSE的标准方案,自动处理消息解析、重连等逻辑:

const getStreamEventSource = () => {
  const eventSource = new EventSource('https://my-domain.com/api/getStream');
  
  // 监听默认消息
  eventSource.onmessage = (event) => {
    console.log('Received SSE data:', event.data);
  };

  // 监听错误
  eventSource.onerror = (error) => {
    console.error('SSE error:', error);
    eventSource.close();
  };

  // 可选:监听自定义事件
  eventSource.addEventListener('custom-event', (event) => {
    console.log('Custom event data:', event.data);
  });
};

方案2:基于Axios在浏览器中处理SSE

若必须使用Axios,需放弃responseType: 'stream',改用以下方式手动处理流式响应:

方式A:利用onDownloadProgress分段读取

const getStreamAxiosBrowser = () => {
  let buffer = '';
  axios.get('https://my-domain.com/api/getStream', {
    headers: {
      'Accept': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    },
    onDownloadProgress: (progressEvent) => {
      // 提取新增的响应片段
      const chunk = progressEvent.target.response.substring(buffer.length);
      buffer += chunk;
      // 按SSE格式拆分完整消息
      const messages = buffer.split(/\n\n/);
      buffer = messages.pop() || ''; // 保留未完成的片段

      messages.forEach(msg => {
        if (!msg.trim()) return;
        // 解析SSE的data字段
        const dataMatch = msg.match(/^data:(.*)$/ms);
        if (dataMatch) {
          console.log('Axios received SSE data:', dataMatch[1].trim());
        }
      });
    }
  })
  .catch(e => {
    console.error('Axios request error:', e);
  });
};

方式B:使用ReadableStream(现代浏览器支持)

依赖浏览器的ReadableStream API读取流式响应:

const getStreamAxiosStream = async () => {
  try {
    const response = await axios.get('https://my-domain.com/api/getStream', {
      headers: {
        'Accept': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
      }
    });

    const reader = response.data.getReader();
    const decoder = new TextDecoder('utf-8');
    let buffer = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      
      buffer += decoder.decode(value, { stream: true });
      const messages = buffer.split(/\n\n/);
      buffer = messages.pop() || '';

      messages.forEach(msg => {
        if (!msg.trim()) return;
        const dataMatch = msg.match(/^data:(.*)$/ms);
        if (dataMatch) {
          console.log('Axios stream data:', dataMatch[1].trim());
        }
      });
    }
  } catch (e) {
    console.error('Axios stream error:', e);
  }
};

内容的提问来源于stack exchange,提问作者NullUserException

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:00:17