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

Vue3中使用fetch和getReader捕获GPT聊天流未捕获的TypeError

问题描述

我正在用Vue3组合式API开发聊天机器人客户端,后端采用FastAPI的POST接口返回StreamingResponse。前端使用fetch结合getReader方法处理流式响应,代码如下:

try {
  fetch('api...', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: jsonPrompt
  })
  .then(response => {
    if (!response.ok || !response.body) {
      return;
    }
  
    const reader = response.body.getReader();
  
    reader.read().then(function processText({ done, value }) {
      if (done) {
        console.log('Stream done');
        return;
      }
    
      const decodedData = new TextDecoder('utf-8').decode(value);
      console.log('decodedData:', decodedData);
      //processStream(decodedData);
    
      return reader.read().then(processText);
    })
  })
  .catch(error => {
    console.error('Error in promise:', error);
  });
}
catch (error) {
  console.error('Error:', error);
}

偶尔会在流已启动但done标志返回true前出现TypeError: network error,响应状态码为200(错误信息:net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK)),且外层try-catch无法捕获该错误:
TypeError: network error

请问如何在getReader处理分片数据时捕获该错误?


解决方案

要捕获流式读取过程中的网络错误,核心是处理reader.read()返回Promise的reject状态——这类错误发生在流读取阶段,而非fetch请求初始化阶段,所以外层try-catch和fetch的catch无法捕获。

方法1:给reader.read()的Promise添加catch回调

修改递归读取逻辑,为每次reader.read()的Promise追加错误捕获回调:

try {
  fetch('api...', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: jsonPrompt
  })
  .then(response => {
    if (!response.ok || !response.body) {
      return;
    }
  
    const reader = response.body.getReader();
    // 统一处理流读取错误
    const handleStreamError = (error) => {
      console.error('流读取错误:', error);
      // 释放读取锁,避免资源泄漏
      reader.releaseLock();
      // 可添加用户提示、状态重置等逻辑
    };
  
    reader.read().then(function processText({ done, value }) {
      if (done) {
        console.log('流读取完成');
        return;
      }
    
      const decodedData = new TextDecoder('utf-8').decode(value);
      console.log('解码后数据:', decodedData);
      //processStream(decodedData);
    
      // 递归读取时捕获错误
      return reader.read().then(processText).catch(handleStreamError);
    }).catch(handleStreamError); // 捕获第一次读取的错误
  })
  .catch(error => {
    console.error('Fetch请求错误:', error);
  });
}
catch (error) {
  console.error('全局错误:', error);
}

方法2:改用async/await语法,简化错误捕获

用async函数包裹流式读取逻辑,直接用try-catch捕获所有阶段的错误,代码可读性更强:

const fetchStream = async () => {
  try {
    const response = await fetch('api...', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: jsonPrompt
    });

    if (!response.ok || !response.body) {
      return;
    }

    const reader = response.body.getReader();
    while (true) {
      try {
        const { done, value } = await reader.read();
        if (done) {
          console.log('流读取完成');
          break;
        }
        const decodedData = new TextDecoder('utf-8').decode(value);
        console.log('解码后数据:', decodedData);
        //processStream(decodedData);
      } catch (streamError) {
        console.error('流读取错误:', streamError);
        reader.releaseLock();
        break;
      }
    }
  } catch (globalError) {
    console.error('请求或全局错误:', globalError);
  }
};

// 调用流式请求函数
fetchStream();

额外提示

  • 错误发生后务必调用reader.releaseLock()释放读取锁,避免占用浏览器资源;
  • net::ERR_HTTP2_PROTOCOL_ERROR 200多与HTTP2连接异常有关,可同步排查后端FastAPI的流式响应配置、服务器的HTTP2设置,比如是否存在响应头不规范、连接提前中断等情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:30:08