UniAPP 微信小程序集成 Dify API 实现流式数据获取与输出

926 阅读2分钟

核心挑战

  1. 微信小程序环境缺乏原生 EventSource 支持
  2. Dify API 的 SSE 数据可能存在非标准格式(如 data:data: 前缀)
  3. 需要处理数据分块、缓冲和消息组帧
  4. 需要保证 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;
  }
}

} }`

关键注意事项

  1. API密钥安全

    • 绝不要在前端硬编码或暴露API密钥
    • 生产环境必须通过后端服务代理请求
    • 开发阶段可使用uniCloud云函数中转
  2. 数据缓冲机制

    • 必须实现缓冲区处理不完整消息
    • 正确处理多字节字符的分块情况
  3. 错误处理

    • 区分网络错误和Dify业务错误
    • 处理JSON解析异常
    • 实现超时重试机制
  4. 性能优化

    • 合理控制UI更新频率
    • 及时释放不再使用的资源
    • 组件卸载时取消未完成请求

最佳实践建议

  1. 使用WebSocket替代方案(如支持)
  2. 实现消息限流和防抖
  3. 添加网络状态监测和自动重连
  4. 对长文本实现分页加载
  5. 添加本地缓存支持
  6. 实现完善的日志记录系统

这个方案已在多个生产环境中验证,能够稳定处理Dify API的流式响应,包括处理非标准SSE格式和微信小程序的环境限制。