阶段六:SSE AI 流式对话
从零构建带AI流式对话的Vue2全栈应用-CSDN博客本文是对这篇文章阶段六的讲解一、普通接口为什么不能产生打字机效果普通接口用户提问 ↓ 后端生成完整回答 ↓ 一次性返回整个回答 ↓ 页面一次性显示SSE用户提问 ↓ 后端保持连接 ↓ 发送第一个字 ↓ 发送第二个字 ↓ 发送第三个字 ↓ 直到结束这就是类似 ChatGPT 的流式输出。二、SSE 是什么SSE 全称Server-Sent Events意思是服务器持续向浏览器发送事件。它主要是单向通信服务器 → 浏览器浏览器使用new EventSource(url)连接服务器。三、SSE 后端响应头res.setHeader( Content-Type, text/event-stream; charsetutf-8 )告诉浏览器这是 SSE 数据而不是普通 JSON。res.setHeader( Cache-Control, no-cache, no-transform )禁止缓存和修改流式内容。res.setHeader( Connection, keep-alive )告诉网络连接不要立刻关闭。res.setHeader( X-Accel-Buffering, no )避免部分代理服务器把数据缓存起来等全部完成后才一次性返回。res.flushHeaders()立即发送响应头。不需要等待第一段正文。四、SSE 消息格式后端res.write( data: ${JSON.stringify(data)}\n\n )SSE 格式要求data: 数据内容每条消息后必须有两个换行。代码中的\n\n就是两个换行。发送sendEvent({ type: content, text: 你 })浏览器收到data: {type:content,text:你}五、为什么要定义不同的事件类型我们自己设计了三种消息{ type: start }表示开始生成。{ type: content, text: 你 }表示新生成了一段文字。{ type: end }表示生成结束。还可以有{ type: error, message: 模型调用失败 }表示错误。六、模拟逐字发送const characters Array.from(answer)把字符串变成字符数组。例如Array.from(你好)得到[你, 好]然后let currentIndex 0记录当前发送到第几个字符。setIntervalconst timer setInterval(() { // 每隔 70 毫秒执行一次 }, 70)每隔 70 毫秒发送一个字符。第一次你第二次好第三次继续。这就产生了打字机效果。发送完成if ( currentIndex characters.length ) { sendEvent({ type: content, text: characters[currentIndex] }) currentIndex 1 return }如果还有字符就发送当前字符。全部发送完成后sendEvent({ type: end }) clearInterval(timer) res.end()clearInterval停止定时器。res.end()关闭 HTTP 响应。七、用户停止生成前端执行this.eventSource.close()浏览器关闭 SSE 连接。后端监听req.on(close, () { clearInterval(timer) })连接关闭后停止继续生成。真实大模型时还应该同时取消上游模型请求避免继续产生费用。八、为什么 SSE 使用EventSource不用 AxiosAxios 更适合普通请求发送请求 等待完整响应 得到结果SSE 需要连接持续存在 不断接收新消息浏览器原生提供EventSource所以使用this.eventSource new EventSource(streamUrl)九、聊天页面中的数据data() { return { question: , messages: [], streamingContent: , isStreaming: false, eventSource: null, nextMessageId: 1 } }questionquestion: 保存输入框内容。模板el-input v-modelquestion /v-model是双向绑定。用户输入文字 → question 变化同时question 变化 → 输入框显示变化messagesmessages: []保存已经完成的历史消息。例如[ { id: 1, role: user, content: 你好 }, { id: 2, role: assistant, content: 你好请问有什么可以帮助你 } ]streamingContentstreamingContent: 保存当前还在生成中的 AI 回答。收到一个字this.streamingContent data.text例如原来你 新字符好 结果你好isStreamingisStreaming: false表示是否正在生成。false可以发送新问题 true正在生成显示停止按钮模板可以根据它切换按钮el-button v-ifisStreaming 停止生成 /el-button el-button v-else 发送 /el-buttoneventSourceeventSource: null保存当前 SSE 连接对象。有了它才能主动执行this.eventSource.close()十、发送问题流程sendQuestion() { const trimmedQuestion this.question.trim() if ( !trimmedQuestion || this.isStreaming ) { return } }先去掉空格。如果问题为空直接结束。如果正在生成也直接结束避免同时建立多个连接。保存用户消息this.messages.push({ id: this.nextMessageId, role: user, content: trimmedQuestion })向数组添加一条用户消息。Vue 发现数组变化后会自动更新页面中的v-formessage in messages清空输入框this.question 因为输入框使用v-modelquestion所以数据变空后输入框也自动清空。建立 SSEconst streamUrl createAiStreamUrl( trimmedQuestion ) this.eventSource new EventSource(streamUrl)最终地址类似/api/ai/stream?question请介绍一下SSE十一、onmessagethis.eventSource.onmessage event { const data JSON.parse(event.data) }每次服务器发送data: ...都会触发onmessage。event.data是字符串。例如{type:content,text:你}通过JSON.parse(event.data)转换成 JavaScript 对象。处理文字if (data.type content) { this.streamingContent data.text || return }每收到一个文字片段就追加到页面。处理结束if (data.type end) { this.finishStream() }finishStream()会把临时回答保存到 messages 关闭 SSE 恢复发送按钮十二、保存流式消息saveStreamingMessage() { if (!this.streamingContent) { return } this.messages.push({ id: this.nextMessageId, role: assistant, content: this.streamingContent }) this.nextMessageId 1 this.streamingContent }生成过程中回答在streamingContent生成完成后转移到messages然后把临时内容清空。十三、为什么要在beforeDestroy关闭连接beforeDestroy() { this.closeEventSource() }当用户离开聊天页面时组件准备销毁。如果不关闭 SSE用户已经进入别的页面 后端仍然继续发送 连接仍占用资源所以离开页面前必须关闭。十四、自动滚动scrollToBottom() { this.$nextTick(() { const container this.$refs.messageContainer container.scrollTop container.scrollHeight }) }$refs模板中div refmessageContainer脚本中可以通过this.$refs.messageContainer获得这个真实 HTML 元素。scrollHeight表示内容总高度。scrollTop表示当前滚动位置。设置scrollTop scrollHeight就会滚动到底部。$nextTickVue 修改数据后真实网页不是立即同步完成。所以先等待 Vue 更新 DOMthis.$nextTick(...)再滚动。十五、为什么阶段五 Cookie 对 SSE 很重要原生EventSource不方便添加自定义请求头。很难像 Axios 一样手动写Authorization: Bearer ...但是浏览器会自动给同源 EventSource 请求携带 Cookie。所以组合是阶段五HttpOnly Cookie 阶段六EventSource后端requireAuth可以正常读取 Cookie判断用户是否登录。

相关新闻

阶段五:HttpOnly Cookie 登录持久化

阶段五:HttpOnly Cookie 登录持久化

从零构建带AI流式对话的Vue2全栈应用-CSDN博客本文是对这篇文章阶段五的讲解 一、阶段五为什么要改 Token 保存方式 阶段四: Token 保存在 Vuex 前端 JavaScript 可以读取 Token 刷新后 Token 消失 阶段五: Token 保存在 HttpOnly Cookie JavaScrip…

2026/7/29 23:48:44 阅读更多 →
番茄钟终极指南:如何用Tomodoro实现深度专注与高效时间管理

番茄钟终极指南:如何用Tomodoro实现深度专注与高效时间管理

番茄钟终极指南:如何用Tomodoro实现深度专注与高效时间管理 【免费下载链接】tomodoro A pomodoro web app with PIP mode, white noise generation, tasks and more! 项目地址: https://gitcode.com/gh_mirrors/to/tomodoro 你是否曾坐在电脑前数小时&#…

2026/7/29 23:48:42 阅读更多 →
HarmonyOS:ArkTS数据模型的设计与演进实战

HarmonyOS:ArkTS数据模型的设计与演进实战

引子:数据设计好了,UI 就是套模板 星空运势应用经历了两次数据结构的变化。第一版是四个文件——Types.ts、SignsData.ts、TarotData.ts、Constants.ts,每个文件职责单一。重构后合并成了一个 DataModel.ets,12 星座的数据从 5 个…

2026/7/28 22:41:04 阅读更多 →

最新新闻

2026年东莞专业木工五轴雕刻机供应商哪家好?看完这篇就懂了

2026年东莞专业木工五轴雕刻机供应商哪家好?看完这篇就懂了

作为全国核心的实木家具、木工文创产业带,东莞每年有近千家工厂要换购或新增五轴雕刻设备,但不少老板踩过坑:要么买的通用五轴不防木屑半年就坏,要么进口设备贵到肉疼售后还等半个月,要么做异形件还要多次翻面装夹成品…

2026/7/30 9:19:46 阅读更多 →
抓包鹰 TraceEagle 实战教程 HTTPS 抓包与自动解密入门

抓包鹰 TraceEagle 实战教程 HTTPS 抓包与自动解密入门

做移动端开发或者接口联调的时候,抓包几乎是每天都要做的事。之前用 Charles 或 Fiddler 配代理、装证书、处理 SSL Pinning,一套流程走下来不轻松。最近发现一款叫 TraceEagle(抓包鹰)的全平台抓包调试工具,开箱即抓、…

2026/7/30 9:19:46 阅读更多 →
记一次codex极简升级过程

记一次codex极简升级过程

在AI爆发的时代不会用codex可不行,但是这里面还是有很多门槛,好不容易下载了codex,我登录了chatgpt的账号后还要短信验证,我哪里有国外的验证码啊,一顿折腾问AI、自己搜索、问朋友,终于搞定这个验证码的问题…

2026/7/30 9:19:46 阅读更多 →
解密prompt系列. MCP实战:从Low-Level到FastMCP的搭建演进

解密prompt系列. MCP实战:从Low-Level到FastMCP的搭建演进

解密prompt系列. MCP实战:从Low-Level到FastMPM的搭建演进 大家好,我是你们的技术老友。今天咱们来聊聊一个在AI应用开发里越来越重要的玩意儿——MCP(Model Context Protocol)。别被这个名字吓到,它其实就是一套让大语…

2026/7/30 9:19:46 阅读更多 →
2026年汽博正规靠谱中医诊所选择指南:获取电话及挑选要点

2026年汽博正规靠谱中医诊所选择指南:获取电话及挑选要点

开头:技术痛点/趋势引入2026年,随着人们对健康重视程度的不断提高,中医诊疗越来越受到关注。在汽博地区,许多人都希望找到一家正规靠谱的中医诊所来调理身体。然而,当前市场上中医诊所众多,质量参差不齐&am…

2026/7/30 9:19:45 阅读更多 →
QtScrcpy深度探索:跨平台Android投屏控制技术的实战解析

QtScrcpy深度探索:跨平台Android投屏控制技术的实战解析

QtScrcpy深度探索:跨平台Android投屏控制技术的实战解析 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy 在移动设备开发、游戏测试和自动化运维领域,如何高效…

2026/7/30 9:18:45 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻