如何在浏览器中通过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
相关产品推荐
相关产品推荐

