微信小程序-处理流式请求(sse)_微信小程序 sse
一、微信小程序-处理流式请求(sse)
目前AI比较火热,很多小程序都接入了AI功能,但是对于AI对话,很多都是使用websocket的解决方案,但是会带来一些复杂度,前后端都需要维护连接的状态。因此AI对话主流方案还是使用sse,相对比较简单和轻量。本文将会介绍微信小程序接入sse的简单示例。
二、基于RequestTask.onChunkReceived,实现流式数据处理
2.1、index.js
// index.js// 请求任务let task = null;Page({ data: { msg: \'\' }, // 取消请求 cancelRequest() { if (task) { console.log(\'cancel\') task.abort() } }, // 发起请求 startRequest() { // 初始化消息内容,可忽略 this.setData({ msg: \'\' }); // 实际发起请求,本文示例使用coze task = wx.request({ url: \'https://api.coze.cn/v3/chat?conversation_id=7519696701909794856\', header: { \'content-type\': \'application/json\', \'Authorization\': \'Bearer pat_Ey1d7Ix9urMKVE99xd7doplsMGAhE4UpwDqe7mP9F5mACb1mJB39q3zAf06p1UQn\' }, method: \'POST\', enableChunked: true, data: { \"bot_id\": \"7478216525708247078\", \"user_id\": \"123456\", \"stream\": true, \"additional_messages\": [ { \"role\": \"user\", \"type\": \"question\", \"content_type\": \"text\", \"content\": \"你好\" } ] }, responseType:\'arraybuffer\', success: (res) => { // 请求完成回调用 }, }); // 缓存数据 let buffer = \'\'; task.onChunkReceived((res) => { // 由于返回数据为二进制,需要进行解析 const chunk = this.decodeChunk(res.data); if (!chunk) return; buffer += chunk; if (buffer.includes(\'\\n\\n\')) { this.parseSSEData(buffer); buffer = \'\'; } }); }, // 处理sse数据 parseSSEData(text) { const messages = text.split(\'\\n\\n\'); for (const message of messages) { // 这里需要根据实际sse内容进行处理 if (!message.includes(\'event:conversation.message.delta\')) continue; const dataMatch = message.match(/data:(.+)/); if (!dataMatch) continue; try { const jsonData = JSON.parse(dataMatch[1]); this.setData({ msg: this.data.msg + jsonData.content }); } catch (e) { console.error(\'JSON解析错误:\', e); } } }, // 解析二进制数据 decodeChunk(data) { // 兼容处理,真机返回的的是 ArrayBuffer if (data instanceof ArrayBuffer) { data = new Uint8Array(data); } try { // 由于小程序真机不支持TextEncoder/TextDecoder,因此需要使用其他方式 return decodeURIComponent(escape(String.fromCharCode.apply(null, data))); } catch (e) { console.error(\'解码错误:\', e); return \'\'; } },})
2.2、index.wxml
<scroll-view class=\"scrollarea\" scroll-y type=\"list\"> <view class=\"container\"> <view class=\"text-box\" scroll-y=\"true\" scroll-top=\"{{scrollTop}}\"> <text>{{msg}}</text> </view> <button bindtap=\"startRequest\">发起请求</button> <button bindtap=\"cancelRequest\">取消请求</button> </view></scroll-view>