跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

DeepSeek API如何实现流式数据在网页端渲染_使用Server-Sent Events接收流式响应

需正确处理SSE协议:一、用fetch+ReadableStream发起请求,响应头含text/event-stream等字段;二、逐行解析data:内容并拼接JSON;三、用textContent追加纯文本防XSS;四、按lastEventId重连并指数退避;五、兼容旧浏览器降级用EventSource或polyfill。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜ 如果您在网页端调用DeepSeek API并希望实时渲染模型返回的流式文本,但响应内容延迟显示或出现乱序、截断现象,则可能是由于未正确处理Server-Sent Events(SSE)协议的数据分块与解析逻辑。以下是实现流式数据在网页端稳定渲染的具体步骤: 一、建立符合SSE规范的HTTP请求 浏览器 需通过EventSource或fetch+ReadableStream发起请求,且服务端响应头必须包含text/event-stream类型及必要的缓存禁用指令,否则浏览器将无法持续接收事件流。 1、使用fetch发送POST请求,设置headers中Content-Type为application/ js on,并在body中传入包含model、messages、stream: true等字段的JSON对象。 2、在fetch的Response对象上调用response.body.getReader()获取可读流,确保不使用response. json ()或response.text()等终结型方法。 3、设置request headers中的Accept为text/event-stream,显式声明客户端支持SSE格式。 4、在服务端返回的HTTP响应头中,必须包含 Content-Type: text/event-stream 、 Cache-Control: no-cache 、 Connection:keep-alive 三项关键字段。 二、解析event: message与data: 字段的原始 字节 流 DeepSeek API的SSE响应并非标准单data行格式,实际每条消息含多行:event: message、id: xxx、data: {json},需逐行扫描换行符并提取data后的内容,否则会将JSON结构体误判为纯文本。 1、对每次read()返回的Uint8Array调用decoder.decode(chunk, {stream: true})转为字符串,避免UTF-8多字节字符被截断。 2、将解码后的字符串按\n分割,遍历每一行,识别以data: 开头的行并去除前缀,保留后续所有字符(包括嵌套JSON中的换行)。 3、当遇到空行时,将已累积的data片段拼接为完整JSON字符串,再通过JSON.parse()提取delta.content字段值。 4、忽略所有不含data: 的行,如event:、id:、retry:等控制字段,防止向UI注入非文本内容。 三、逐字符追加至DOM并防XSS注入 流式内容需以最小粒度更新页面,但直接innerHTML赋值存在脚本执行风险;应仅提取纯文本并使用textContent或createTextNode插入,同时保留换行与空格语义。 1、创建一个预置的
容器,设置CSS white-space: pre-wrap确保换行符生效。 2、每次解析出delta.content后,调用document.getElementById('output').appendChild(document.createTextNode(content))。 Comet AI 浏览器 下载 Comet AI 浏览器,体验由 Perplexity AI 驱动的革命性上网方式。内置 AI 助手可实时总结网页、跨标签页对比信息、自动执行任务。告别繁琐操作,让 AI 成为你的浏览副驾,大幅提升研究与工作效率。支持 Windows、macOS、Android 和 iOS。 下载 3、若content含\n字符,在插入前将其替换为'\n',而非 标签,因pre元素原生支持换行渲染。 4、禁止将content作为HTML字符串拼接后赋给innerHTML,防止 恶意payload如被执行 。 四、处理流中断与重连逻辑 网络抖动或服务端超时会导致ReadableStream关闭,此时需检测done状态并触发自动重试,避免用户界面停滞;但重试必须携带上次成功接收的id,否则将重复返回历史片段。 1、在read() Promise拒绝或done为true时,检查lastEventId是否为空,若非空则在请求URL后添加?last_id=xxx参数。 2、设置指数退避重试间隔,首次延迟1秒,第二次2秒,第三次4秒,上限不超过30秒。 3、在重连请求头中添加 X-Last-Event-ID: {lastEventId} ,供服务端定位续传位置。 4、限制最大重试次数为5次,超过后向用户显示 “连接已断开,请刷新页面重试” 提示。 五、适配不同浏览器的流式读取兼容性 Safari 15.4以下版本不支持ReadableStream默认构造,且部分 安卓 WebView对TextDecoder.stream()无响应;需降级使用EventSource并手动解析data字段,或引入web-streams-polyfill。 1、检测window.EventSource是否存在,若存在且navigator.userAgent包含Safari,则优先使用EventSource初始化。 2、若使用fetch,则在调用前判断window.ReadableStream是否可用,不可用时加载 https://cdn.jsdelivr.net/npm/web-streams-polyfill@3.2.1/dist/ponyfill.min.js 。 3、对EventSource实例监听message事件,从e.data提取JSON字符串,再执行与步骤二相同的data字段剥离逻辑。 4、禁用EventSource的自动重连机制(设置eventSource.readyState = 0),由自定义逻辑统一控制重试时机与参数。

相关文章