从流中获取的数据格式如下
小程序调用SSE接口
const requestTask = wx.request({
url: `xxx`, // 需要请求的接口地址
enableChunked: true, // enableChunked必须为true
method: "GET",
timeout: '120000',
success(res) {
console.log(res.data)
},
fail: function (error) {
// 请求失败的操作
console.error(error);
},
complete: function () {
// 请求完成的操作,无论成功或失败都会执行
console.log('请求完成', str);
}
})
// 监听服务端返回的数据
requestTask.onChunkReceived(res => {
console.log( res, res.data);
})
我这边接收到的数据类型为Uint8Array,需要处理成text文本(如上图)
// 监听服务端返回的数据
requestTask.onChunkReceived(res => {
console.log( res, res.data);
// Uint8Array转为text格式
let arrayBuffer = res.data;
let decoder = new TextDecoder('utf-8');
let text = decoder.decode(arrayBuffer);
//正则匹配上所有event:data后面的文字
const eventRegex = /event:data\ndata:"data:(.*?)"/g;
const eventRegexErr = /event:600\ndata:"(.*?)"/g;
let matches = [];
let match;
if (text.indexOf('600') != -1) {//如果获取响应失败
while ((match = eventRegexErr.exec(text)) !== null) {
wx.showToast({
title: match[1],
})
matches.push(match[1]);
}
str = str + matches.join('')
} else {//如果获取响应成功
while ((match = eventRegex.exec(text)) !== null) {
matches.push(match[1]);
}
//处理成字符串
str = str + matches.join('')
console.log(text, str);
}
})
使对话有打字机效果
参考自:小程序实现 ChatGPT 聊天打字兼自动滚动效果
that.handleRequestResolve(str)
handleRequestResolve(result) {
const timestamp = Date.now();
const index = this.data.messageList.length
const newMessageList = `messageList[${index}]`
const contentCharArr = result.trim().split("")
const content_key = `messageList[${index}].content`
const finished_key = `messageList[${index}].finished`
this.setData({
thinking: false,
[newMessageList]: {
id: timestamp,
finished: false
}
})
currentContent = ''
this.showText(0, content_key, finished_key, contentCharArr);
},
showText(key = 0, content_key, finished_key, value) {
/* 所有内容展示完成 */
if (key >= value.length) {
this.setData({
loading: false,
[finished_key]: true
})
// wx.vibrateShort()
return;
}
currentContent = currentContent + value[key]
/* 渲染回话内容 */
this.setData({
[content_key]: currentContent,
})
setTimeout(() => {
/* 递归渲染内容 */
this.showText(key + 1, content_key, finished_key, value);
}, 50);
},
完整代码
getDataStream(data) {
let str = ''
let that = this
// 基础库为2.33.0
const requestTask = wx.request({
enableChunked: true, // 开启分片模式
url: 'xxx', // 需要请求的接口地址
enableChunked: true, // enableChunked必须为true
method: "GET",
responseType: "arraybuffer",
timeout: '120000',
success(res) {
console.log(res.data)
},
fail: function (error) {
// 请求失败的操作
console.error(error);
},
complete: function () {
// 请求完成的操作,无论成功或失败都会执行
console.log('请求完成', str);
}
})
// 监听服务端返回的数据
requestTask.onChunkReceived(res => {
console.log(res, res.data);
// Uint8Array转为text格式
let arrayBuffer = res.data;
let decoder = new TextDecoder('utf-8');
let text = decoder.decode(arrayBuffer);
//正则匹配上所有event:data后面的文字
const eventRegex = /event:data\ndata:"data:(.*?)"/g;
const eventRegexErr = /event:600\ndata:"(.*?)"/g;
let matches = [];
let match;
if (text.indexOf('600') != -1) { //如果获取响应失败
while ((match = eventRegexErr.exec(text)) !== null) {
wx.showToast({
title: match[1],
})
matches.push(match[1]);
}
str = str + matches.join('')
} else { //如果获取响应成功
while ((match = eventRegex.exec(text)) !== null) {
matches.push(match[1]);
}
//处理成字符串
str = str + matches.join('')
console.log(text, str);
}
that.handleRequestResolve(str)
})
requestTask.offChunkReceived(res => {
console.log('事件完成状态');
})
},
handleRequestResolve(result) {
const timestamp = Date.now();
const index = this.data.messageList.length
const newMessageList = `messageList[${index}]`
const contentCharArr = result.trim().split("")
const content_key = `messageList[${index}].content`
const finished_key = `messageList[${index}].finished`
this.setData({
thinking: false,
[newMessageList]: {
id: timestamp,
finished: false
}
})
currentContent = ''
this.showText(0, content_key, finished_key, contentCharArr);
},
showText(key = 0, content_key, finished_key, value) {
/* 所有内容展示完成 */
if (key >= value.length) {
this.setData({
loading: false,
[finished_key]: true
})
// wx.vibrateShort()
return;
}
currentContent = currentContent + value[key]
/* 渲染回话内容 */
this.setData({
[content_key]: currentContent,
})
setTimeout(() => {
/* 递归渲染内容 */
this.showText(key + 1, content_key, finished_key, value);
}, 50);
},