当前位置: 首页 > news >正文

如何取消 fetch 的流式请求并处理错误信息

引言:

最近在做的ai项目,产品提了一个需求,要求如果ai正在输出内容,用户再次提交了prompt,终止当前的请求,去发送新的请求

代码示例

封装请求

export const getAiMessage = ({ message, session_id, callback, signal }) => {
  fetch(`${baseURL}/api/question/ask`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: sessionStorage.getItem("token") || "",
    },
    body: JSON.stringify({ message, session_id: session_id || "" }),
    signal: signal,
  })
    .then(async (response) => {
      // 请求成功
      if (response.ok) {
        const reader = response.body.getReader();
        const decoder = new TextDecoder("utf-8");
        while (true) {
          try {
            const { value, done } = await reader.read();
            if (done) {
              break;
            }
            const chunkValue = decoder.decode(value).split("\n\n");
            for (const item of chunkValue) {
              if (item.startsWith("data:")) {
                const itemData = JSON.parse(item.replace("data:", " ").trim());
                callback(itemData);
              }
            }
          } catch (e) {
            if (e.name === "AbortError") {
              console.log("请求已取消", e);
              return;
            }
            console.log("数据流读取出错", e);
          }
        }
        console.log("响应结束");
      }
    })
    .catch((e) => {
      if (e.name === "AbortError") {
        console.log("请求已取消", e);
      } else {
        console.log("请求出错", e);
      }
    });
};

页面使用 

handleSend(e) {
      if (e) {
        e.preventDefault();
      }
      if (!this.userPrompt || this.isMessageLoading) {
        return;
      }
      if (this.streamController) {
        this.streamController.abort();
      }
      this.isMessageLoading = true;
      this.aiMessageList.push({
        role: "user",
        content: this.userPrompt,
      });
      this.changeMessageScroll();
      const aiMessageIndex = this.aiMessageList.length;
      this.aiMessageList[aiMessageIndex] = {
        role: "assistant",
        content: "",
      };
      this.streamController = new AbortController();
      const obj = {
        message: this.userPrompt,
        session_id: this.session_id,
        callback: (res) => {
          this.isMessageLoading = false;
          this.result += res.text;
          this.session_id = res.session_id;
          const converter = new showdown.Converter();
          this.aiMessageList[aiMessageIndex] = {
            role: "assistant",
            content: converter.makeHtml(this.result),
          };
          this.changeMessageScroll();
        },
        signal: this.streamController.signal,
      };
      this.userPrompt = "";
      this.result = "";
      getAiMessage(obj);
    },

代码详解

我们主要通过创建AbortController对象,将AbortController中的signal传递给fetch,然后通过调用AbortController的abort方法去取消请求,主要代码如下

 

如果想取消请求,在想取消请求的代码逻辑处 调用abort方法就好

错误处理 

成功取消请求后会被 catch 捕获。注意 ! ! ! !,如果使用的是流式请求,一定要在每次处理接收到的流数据时进行错误处理,并在捕获到错误时使用 return 退出当前方法。否则,请求会继续进行,并且错误信息会不断打印,导致页面卡死。因为我们取消请求,也只是抛出了一个请求取消的报错信息,具体的代码逻辑需要我们自己处理。

 

相关文章:

  • 永恒之地.天雷降世(第四章)第二册完结
  • DigitalOcean 发布 AMD Instinct MI300X GPU 裸金属服务器
  • C++学习之取证综合软件首页QT实现
  • 安徽人工智能企业能申报什么政策?安徽人工智能产业项目申报大全
  • 动态循环表单+动态判断表单类型+动态判断表单是否必填方法
  • 基于Deepface的情绪识别c++
  • HOW - Axios 拦截器特性
  • 量子芯火燎原:AI算力革命的密码
  • RabbitMQ高级特性1
  • Ubuntu 24 云服务器上部署网站_详细版_1
  • 关于c++ trt推理YOLO系列,出现检测框混乱,集中左上角的问题
  • git技法-对比master和release两个版本差异提交
  • 搭建redis遇到问题:
  • PVE如何查看某块硬盘被哪些虚拟机使用
  • 使用axios发请求
  • 华为项目管理“六步一法”方法论全解析:目标确认、项目活动分解与日事清系统协同
  • 基于51单片机的贪吃蛇小游戏proteus仿真
  • 通过 C# 提取PDF文档中的图片
  • C++ | 文件读写(ofstream/ifstream/fstream)
  • 谷歌TV认证,谷歌TADA认证,谷歌电视认证介绍