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

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实现:

  1. 安装依赖:
npm install web-streams-polyfill
  1. 在应用入口文件(如main.ts)中引入polyfill:
import 'web-streams-polyfill/polyfill';
  1. 保留原Axios代码不变,重新运行应用测试。

说明

  • 优先推荐方案1,原生Fetch的流式处理在Safari中兼容性最好,无需依赖Axios的适配器逻辑。
  • 方案2适合必须使用Axios生态的场景,但需要手动处理流式数据的拼接和转换。
  • 方案3通过polyfill补全API,但可能引入额外的代码体积,需权衡使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 09:50:06