核心挑战
- 微信小程序环境缺乏原生 EventSource 支持
- Dify API 的 SSE 数据可能存在非标准格式(如
data:data:前缀) - 需要处理数据分块、缓冲和消息组帧
- 需要保证 API 密钥的安全性
技术实现方案
1. 认证与请求配置
const requestTask = uni.request({ url: 'https://api.dify.ai/v1/chat-messages', method: 'POST', header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_API_KEY' // 实际生产环境应通过后端代理 }, data: { query: "用户输入的问题", response_mode: "streaming", user: "user123" }, enableChunked: true, // 关键配置 responseType: 'arraybuffer', // 推荐使用arraybuffer success(res) { console.log('连接建立', res); }, fail(err) { console.error('请求失败', err); } });
2. 流式数据处理核心逻辑
` let buffer = '';
requestTask.onChunkReceived((chunk) => { // 1. ArrayBuffer转文本 const textChunk = new TextDecoder('utf-8').decode(chunk.data);
// 2. 缓冲数据 buffer += textChunk;
// 3. 提取完整SSE消息 let delimiterIndex; while ((delimiterIndex = buffer.indexOf('\n\n')) !== -1) { const rawSseMessage = buffer.substring(0, delimiterIndex); buffer = buffer.substring(delimiterIndex + 2);
// 4. 解析SSE消息
parseSseMessage(rawSseMessage);
} });
function parseSseMessage(rawMessage) { let eventName = ''; let dataPayload = '';
rawMessage.split('\n').forEach(line => { // 处理Dify特有的data:data:前缀 if (line.startsWith('data: data: ')) { dataPayload += line.substring('data: data: '.length); } else if (line.startsWith('data:')) { dataPayload += line.substring('data:'.length); } else if (line.startsWith('event:')) { eventName = line.substring('event:'.length).trim(); } });
// 处理有效载荷 if (dataPayload) { try { const parsedData = JSON.parse(dataPayload.trim()); handleDifyEvent(eventName, parsedData); } catch (e) { console.error('JSON解析错误', e); } } } `
3. Dify事件处理
`// Vue组件中 export default { data() { return { currentMessage: '', isLoading: false } }, methods: { handleDifyEvent(eventName, data) { switch (eventName) { case 'message': this.currentMessage += data.answer; // 流式更新UI break;
case 'message_end':
this.isLoading = false;
// 处理元数据等
break;
case 'error':
this.isLoading = false;
uni.showToast({ title: data.message, icon: 'none' });
break;
}
}
} }`
关键注意事项
-
API密钥安全
- 绝不要在前端硬编码或暴露API密钥
- 生产环境必须通过后端服务代理请求
- 开发阶段可使用uniCloud云函数中转
-
数据缓冲机制
- 必须实现缓冲区处理不完整消息
- 正确处理多字节字符的分块情况
-
错误处理
- 区分网络错误和Dify业务错误
- 处理JSON解析异常
- 实现超时重试机制
-
性能优化
- 合理控制UI更新频率
- 及时释放不再使用的资源
- 组件卸载时取消未完成请求
最佳实践建议
- 使用WebSocket替代方案(如支持)
- 实现消息限流和防抖
- 添加网络状态监测和自动重连
- 对长文本实现分页加载
- 添加本地缓存支持
- 实现完善的日志记录系统
这个方案已在多个生产环境中验证,能够稳定处理Dify API的流式响应,包括处理非标准SSE格式和微信小程序的环境限制。