文章目录
- 一、背景概述
- 二、核心流程图解
- 三、代码模块详解
-
- [1. UTF-8解码器(处理二进制流)](#1. UTF-8解码器(处理二进制流))
- [2. 请求控制器(核心通信模块)](#2. 请求控制器(核心通信模块))
- [3. 流式请求处理器(分块接收)](#3. 流式请求处理器(分块接收))
- [4. 数据解析器(处理SSE格式)](#4. 数据解析器(处理SSE格式))
- [5. 回调处理三剑客](#5. 回调处理三剑客)
- 四、关键问题解决方案
-
- [1. 乱码问题处理](#1. 乱码问题处理)
- [2. 数据截断问题](#2. 数据截断问题)
- [3. 性能优化建议](#3. 性能优化建议)
- 五、扩展思考
-
- [1. 为什么要用SSE而不是WebSocket?](#1. 为什么要用SSE而不是WebSocket?)
- [2. 流量控制策略](#2. 流量控制策略)
- 六、完整技术栈推荐
一、背景概述
在大模型应用中,流式响应技术(Server-Sent Events, SSE)能显著提升用户体验。本文将以代码为核心,讲解基于uni-app框架的流式交互完整实现方案,涵盖数据接收、解码、解析全流程。
二、核心流程图解
用户输入 构建请求体 发送SSE请求 接收数据块 二进制解码 数据清洗 解析JSON 提取内容 实时渲染
三、代码模块详解
1. UTF-8解码器(处理二进制流)
javascript
decodeUTF8(data) {
// 将二进制数据转为Uint8数组
const uint8Array = new Uint8Array(data);
// 传统方式转换字符串(兼容旧环境)
let string = '';
for (let i = 0; i < uint8Array.length; i++) {
string += String.fromCharCode(uint8Array[i]);
}
// 双重解码处理特殊字符(如中文)
return decodeURIComponent(escape(string));
}
关键点说明:
Uint8Array
:将原始二进制数据转为可操作数组escape()
:将字符串转义为ASCII字符decodeURIComponent
:解析URI编码内容(等效于UTF-8解码)
2. 请求控制器(核心通信模块)
javascript
getContent() {
const sendContent = {
"messages": [{
"role": "user",
"content": this.content,
}],
"section_id": this.id,
"token": this.token
}
// 显示等待状态
this.waitingForResponse = true;
// 发起流式请求
this.streamPost('/api/xxx/xxx',
sendContent,
this.onDataReceived,
this.onError,
this.onComplete);
}
参数解析:
参数名 | 类型 | 说明 |
---|---|---|
role | String | 角色标识(user/assistant) |
content | String | 用户输入的提问内容 |
section_id | Number | 会话分区ID |
token | String | 用户身份验证令牌 |
3. 流式请求处理器(分块接收)
javascript
streamPost(url, data, onData, onError = null, onComplete = null) {
const requestTask = uni.request({
url: this.$baseUrl + url,
method: 'POST',
header: {
'Accept': 'text/event-stream', // 声明接受事件流
'token': uni.getStorageSync('token')
},
data,
enableChunked: true, // 启用分块传输模式
responseType: 'arraybuffer', // 接收二进制数据
// 分块数据到达时触发
success: (res) => { /*...*/ },
// 注册分块接收监听器
onChunkReceived: (res) => {
const decodedData = this.decode(res.data);
if (decodedData) {
onData(decodedData); // 触发数据回调
}
}
});
}
技术要点:
enableChunked: true
:启用微信小程序分块接收能力responseType: 'arraybuffer'
:确保正确处理二进制流onChunkReceived
:微信小程序特有分块事件监听
4. 数据解析器(处理SSE格式)
javascript
decode(data) {
const text = this.decodeUTF8(data);
const lines = text.split('\n');
let result = '';
for (let line of lines) {
if (line.startsWith('data: ')) {
const jsonData = line.slice(6).trim();
// 结束标识处理
if (jsonData === '[DONE]') return result;
// 清理控制字符(防止JSON解析失败)
const cleanedData = jsonData.replace(/[\u0000-\u001F\u007F-\u009F]/g, '');
try {
const parsedData = JSON.parse(cleanedData);
// 提取AI生成内容
result += parsedData.choices[0].delta.content || '';
} catch (e) {
console.error('解析失败:', e);
}
}
}
return result;
}
数据示例:
javascript
// 原始SSE数据格式
data: {"id":"chatcmpl-123","choices":[{"delta":{"content":"你好"}}]}
// 解析后结果
"你好"
5. 回调处理三剑客
javascript
// 实时数据渲染
onDataReceived(data) {
if (data.trim()) {
this.displayText += data; // 增量更新显示内容
this.resultCount = this.displayText.length; // 统计字数
}
}
// 异常处理
onError(error) {
console.error('请求异常:', error);
uni.showToast({ title: '服务响应异常', icon: 'none' });
}
// 完成处理
onComplete() {
this.waitingForResponse = false;
console.log('会话结束');
// 可添加历史记录存储等逻辑
}
四、关键问题解决方案
1. 乱码问题处理
- 现象 :接收到
å"å•Š
类乱码 - 解决方案 :
- 检查
decodeUTF8
是否被正确调用 - 验证服务端编码是否为UTF-8
- 替换解码方案为
new TextDecoder().decode(uint8Array)
- 检查
2. 数据截断问题
-
现象 :JSON解析报错
Unexpected end of JSON input
-
处理策略 :
javascript// 增加数据清洗步骤 const cleanedData = jsonData .replace(/\n/g, '') // 移除换行符 .replace(/\u2028/g, '') // 处理行分隔符 .replace(/\u2029/g, ''); // 处理段落分隔符
3. 性能优化建议
javascript
// 使用文档片段批量更新
let fragment = '';
onDataReceived(data) {
fragment += data;
if (fragment.length > 100) { // 每100字符更新一次
this.displayText += fragment;
fragment = '';
}
}
五、扩展思考
1. 为什么要用SSE而不是WebSocket?
- SSE优势 :
- 基于HTTP协议,无需额外握手
- 自动重连机制
- 更简单的服务端实现
2. 流量控制策略
javascript
// 节流处理(每500ms更新一次)
let updateTimer = null;
onDataReceived(data) {
this.buffer += data;
if (!updateTimer) {
updateTimer = setTimeout(() => {
this.displayText += this.buffer;
this.buffer = '';
updateTimer = null;
}, 500);
}
}
六、完整技术栈推荐
层级 | 技术选型 |
---|---|
前端框架 | Vue3 + uni-app |
状态管理 | Pinia |
HTTP库 | uni.request |
数据格式 | JSON + SSE |
部署环境 | 微信小程序 + Web |
通过以上实现方案,开发者可以构建出高可用的大模型流式交互系统。建议在实际项目中加入加载状态提示 、错误重试机制 和历史会话管理等功能模块,以提升完整用户体验。