1. 理解核心机制:拼接而非替换
Dify 的 streaming 模式下,服务器会不断推送形如 data: {"event": "message", "answer": "字"} 的数据包。
核心逻辑是: 收到一个包,解析出 answer 字段,将其**追加(Append)**到当前正在显示的对话变量后,而不是直接替换。
2. 关键数据解析逻辑
Dify 返回的数据流格式如下:
data: {"event": "message", "answer": "我", ...}\n\n data: {"event": "message", "answer": "是", ...}\n\n data: {"event": "message_end", ...}\n\n
处理难点:
- 前缀处理:每行数据都以
data:开头,解析 JSON 前必须去掉。 - 粘包处理:有时候一次网络请求回调会收到多条
data,需要用\n\n分割。 - 事件区分:必须判断
event字段。message: 文本块,核心展示内容。message_replace: 敏感词替换,需要替换整段文本。message_end: 结束标志。ping: 心跳,忽略即可。
3. UniApp 代码实现方案
在 UniApp 中(特别是微信小程序端),不能直接使用浏览器原生的 EventSource。推荐使用 uni.request 的 enableChunked: true 参数。
以下是一个完整的处理示例代码:
// 假设这是发送消息的方法
sendMessage(userQuery) {
const that = this;
// 1. 在界面先创建一个空的回答占位(为了立刻显示 loading 或光标)
this.messageList.push({ role: 'user', content: userQuery });
this.messageList.push({ role: , : });
currentMsgIndex = .. - ;
requestTask = uni.({
: ,
: ,
: {
: ,
:
},
: {
: {},
: userQuery,
: ,
: ,
: that. ||
},
: ,
: {
}
});
requestTask.( {
});
requestTask.( {
arrayBuffer = res.;
uint8Array = (arrayBuffer);
text = ;
{
decoder = ();
text = decoder.(uint8Array, { : });
} (e) {
text = ..(, uint8Array);
text = ((text));
}
that.(text, currentMsgIndex);
});
},
() {
lines = chunkText.();
lines.( {
(line.()) {
jsonStr = line.(, );
{
data = .(jsonStr);
(data. === ) {
.[msgIndex]. += data.;
(!. && data.) {
. = data.;
}
} (data. === ) {
.[msgIndex]. = data.;
} (data. === ) {
.(, data);
} (data. === ) {
.(, data);
.[msgIndex]. += + data. + ;
}
} (e) {
.(, e);
}
}
});
}


