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

用fetch-event-source处理流式消息:Vue 3中实现openAI/DeepSeek的实时输出

microsoft/fetch-event-source 是一个由微软开发的开源库,旨在提供比浏览器原生 EventSource API 更强大的 Server-Sent Events (SSE) 请求处理能力

核心优势

  • ‌完全兼容 Fetch API‌:支持所有 HTTP 方法和自定义头部
  • 智能重试控制‌:开发者可以完全控制连接中断时的重试策略
  • 灵活的错误处理‌:提供完善的错误处理机制

一、安装依赖

npm install @microsoft/fetch-event-source

二、基本使用

import { fetchEventSource } from '@microsoft/fetch-event-source';await fetchEventSource('/api/sse-endpoint', {method: 'GET', // 支持 GET/POST/PUT 等 HTTP 方法headers: {'Content-Type': 'application/json','Authorization': 'Bearer your-token'},body: JSON.stringify({query: '你的查询内容'})onopen(response) {if (response.ok) {console.log('SSE连接成功');} else {throw new Error(`连接失败: ${response.status}`);}},onmessage(event) {console.log('收到消息:', event.data); //这里的消息就是流式输出的},onclose() {console.log('SSE连接关闭');},onerror(err) {console.error('发生错误:', err);throw err; // 抛出错误会停止重试}
});

三、封装成hooks

import { fetchEventSource } from '@microsoft/fetch-event-source';
import { ref, onUnmounted } from 'vue';interface EventSourceOptions {url: string;method?: 'GET' | 'POST';body?: any;onMessage?: (data: string) => void;onOpen?: (response: Response) => void;onError?: (err: any) => void;
}export function useEventSource() {const error = ref<any>(null);const isLoading = ref<boolean>(false);let controller: AbortController | null = null;const fetchStream = async (options: EventSourceOptions) => {isLoading.value = true;error.value = null;controller = new AbortController();try {await fetchEventSource(options.url, {method: options.method || 'GET',headers: {'Content-Type': 'application/json','Accept': "text/event-stream",},body: options.body ? JSON.stringify(options.body) : undefined,signal: controller.signal,// 建立链接onopen: async (response) => {if (response.ok && response.status == 200) {options.onOpen?.(response);}},// 接收消息onmessage: (event) => {if (event.data) {options.onMessage?.(JSON.parse(event.data));}},onerror: (err) => {options.onError?.(err);// 必须抛出错误才会停止重试throw err;},onclose: () => {isLoading.value = false;}});} catch (err) {console.log("链接失败");error.value = err;isLoading.value = false;}};// 主动中断链接const disconnect= () => {if (controller) {controller.abort();isLoading.value = false;}};onUnmounted(() => {disconnect();});return {isLoading,fetchStream,disconnect,onerror,onclose,};
}

四、使用hooks

<template><div><button @click="sendMessage" :disabled="isLoading">{{ isLoading ? '发送中...' : '发送消息' }}</button><div class="stream-content">{{ data }}</div></div>
</template><script setup lang="ts">
import { ref } from 'vue';
import { useEventSource } from '@/composables/useEventSource';const { isLoading, fetchStream } = useEventSource();const data = ref('')const sendMessage = async () => {await fetchStream({url: '/api/chat',method: 'POST',body: {content: '你好,请帮我回答这个问题'},onMessage: (content) => {console.log('收到数据:', content);data.value += content},onOpen: (response) => {console.log('连接已建立');},onError: (err) => {console.error('连接错误:', err);}});
};
</script>
http://www.dtcms.com/a/607712.html

相关文章:

  • Vue 内置指令
  • 龙岩网站设计制作汽车之家网站是谁做的
  • 自己创建网站赚钱合肥市城乡和建设网站
  • 企业局域网组建与网站建设frontpage怎么改网站名字
  • 门户网站开发要求定制网站为什么贵
  • 西部数码怎么上传网站网站员工风采
  • 蚌埠响应式网站开发西安软件开发培训机构
  • 海宁网站开发网站建设私单
  • 林业网站模板微信如何制作网页
  • 手机网站跳出率低新郑做网站公司
  • 开滦建设集团网站网站已经编辑好了 上线准备哪些工作
  • 天津高端网站定制jsp 做网站需要什么软件
  • LeetCode算法日记 - Day 102: 不相交的线
  • 在datagrip里面如何同时操作多行【列选择模式】
  • 石家庄网站排名推广网站规划的原则
  • 关于建设部门子网站的请示app拉新渠道
  • 现在淘客做网站还行吗wordpress悬浮反馈
  • 合肥寒假兼职工网站建设苏州优化外包
  • 医院网站和微信公众号建设方案如皋住房和城乡建设局网站
  • 网站需要的栏目和内容鲜花网站建设规模设想
  • 网站建设套餐表推广网站怎么制作
  • 网页设计是什么意思seo咨询常德
  • 13.RTC实时时钟
  • 算法竞赛中的队列
  • 郑州网站竞价托管上传图片分享链接
  • 网站建设属于什么职位六盘水网站开发
  • 在线做爰直播网站广州注册公司一网通
  • HashSet和LinedHashSet
  • MyBatis学习
  • 在国外做h网站怎么样越南的网站建设