Axios结合ReadableStream在Safari失效,Chrome/Firefox正常
Safari中Axios流式请求报错ReadableByteStreamController未实现的解决方法
问题背景
开发的AI聊天应用采用流式返回响应,在Chrome和Firefox中正常运行,但在Safari中发起Axios请求时触发错误:TypeError: ReadableByteStreamController is not implemented,请求快速结束,未进入响应处理阶段。使用的Axios请求代码如下:
async stream(data: any) { try { console.log("Sending request") const response = await instance.post(this.baseUrl, data, { headers: { 'Accept': 'text/event-stream', }, responseType: 'stream', adapter: 'fetch' }); // Handle response data console.log("Request sent") return { data: response.data, error: null }; } catch (error) { // Handle errors const handledError = await handleError(error); return { data: null, error: handledError }; } }
解决方案1:改用原生Fetch API处理流式请求
Axios的fetch适配器在Safari中对ReadableStream的兼容性不佳,直接使用原生Fetch可以绕过这个问题,原生Fetch在Safari中对流式响应的支持更稳定。
替换后的代码:
async stream(data: any) { try { console.log("Sending request"); const response = await fetch(this.baseUrl, { method: 'POST', headers: { 'Accept': 'text/event-stream', 'Content-Type': 'application/json' // 根据数据格式调整,若为FormData则移除 }, body: JSON.stringify(data), credentials: 'same-origin' // 保持和原Axios请求一致的凭证设置 }); if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } console.log("Request sent"); return { data: response.body, error: null }; } catch (error) { const handledError = await handleError(error); return { data: null, error: handledError }; } }
解决方案2:使用Axios默认XHR适配器处理流式响应
如果必须保留Axios,移除adapter: 'fetch'配置,改用默认的XHR适配器,通过onDownloadProgress事件获取流式数据并封装为ReadableStream:
async stream(data: any) { return new Promise((resolve) => { try { console.log("Sending request"); const stream = new ReadableStream({ start(controller) { instance.post(this.baseUrl, data, { headers: { 'Accept': 'text/event-stream', }, responseType: 'text', // XHR流式处理用text类型 onDownloadProgress: (progressEvent) => { const chunk = progressEvent.target.response.substr(progressEvent.target.response.lastIndexOf('\n') + 1); if (chunk) { controller.enqueue(new TextEncoder().encode(chunk)); } }, complete: () => { controller.close(); console.log("Request sent"); resolve({ data: stream, error: null }); }, error: (err) => { controller.error(err); handleError(err).then(handledError => { resolve({ data: null, error: handledError }); }); } }); } }); } catch (error) { handleError(error).then(handledError => { resolve({ data: null, error: handledError }); }); } }); }
解决方案3:添加Web Streams Polyfill
安装web-streams-polyfill来补全Safari中缺失的ReadableByteStreamController实现:
- 安装依赖:
npm install web-streams-polyfill
- 在应用入口文件(如
main.ts)中引入polyfill:
import 'web-streams-polyfill/polyfill';
- 保留原Axios代码不变,重新运行应用测试。
说明
- 优先推荐方案1,原生Fetch的流式处理在Safari中兼容性最好,无需依赖Axios的适配器逻辑。
- 方案2适合必须使用Axios生态的场景,但需要手动处理流式数据的拼接和转换。
- 方案3通过polyfill补全API,但可能引入额外的代码体积,需权衡使用。
内容的提问来源于stack exchange,提问作者mikeboe
相关产品推荐
相关产品推荐

