H5页面/pc端:@microsoft/fetch-event-source

 1. 安装依赖

首先安装必要的依赖:

npm install @microsoft/fetch-event-source

 2. 添加代码

sendMessageSSEH5(id, userId, question) {
				let that = this;
				let len = this.msgList.length;
				let str = '';
				fetchEventSource('/api/xlx-chat/chatMessage/sendMessageSSE', {
					method: 'POST',
					headers: this.setHeaders(),
					body: JSON.stringify({
						id,
						userId,
						question
					}),
					onopen(response) {
						if (response.ok) {
							console.log('SSE连接成功');
						} else {
							throw new Error('连接失败');
						}
					},
					onmessage(msg) {
						// ...原有处理逻辑
						let {
							data
						} = msg;
						if (data &&
							!data.includes('<br/><br/>tokens') &&
							!data.includes('[DONE]')
						) {
							let parseData = JSON.parse(data);
							str += parseData.content;
							// 数据更新视图不更新==>解决办法是 $set
							that.$set(that.msgList, len, {
								role: 'system',
								content: str
							})
						}
					},
					onerror(err) {
						console.error('SSE错误:', err);
						// 实现重连逻辑
					},
					openWhenHidden: true // 即使页面隐藏也保持连接
				});
			},
			

微信小程序:uni.request+enableChunked

sendMessageSSEWX(id, userId, question) {
				let that = this;
				let len = this.msgList.length;
				let str = '';
				console.log(this.setHeaders());
				let requestTask = uni.request({
					url: 'https://ai.xuexiluxian.cn/api/xlx-chat/chatMessage/sendMessageSSE',
					enableChunked: true, //这个地方需要开启
					header: this.setHeaders(), //这里是header
					method: 'post',
					data: JSON.stringify({
						id,
						userId,
						question
					}),
					success(res) { //这里的success相当于close==》而且必须写,不写下面的事件用不了
						console.log('连接关闭', res);
					}
				})
				requestTask.onHeadersReceived(res => { //等同于 onopen
					console.log('连接是否成功', res);
				})
				requestTask.onChunkReceived(res => { //等同于 onmessage
					const arrayBuffer = res.data;
					const uint8Array = new Uint8Array(arrayBuffer);
					let data = uni.arrayBufferToBase64(uint8Array);
					data = new Buffer(data, 'base64');
					data = data.toString('utf8');
					const lines = data.split('\n\n');


					lines.forEach(line => {
						if (line.indexOf('{') != -1) {
							const dataMatch = line.match(/data:(\{.*\})/);
							if (dataMatch && dataMatch[1]) {
								const dataString = dataMatch[1];
								try {
									data = JSON.parse(dataString);
									str += data.content;
									that.$set(that.msgList, len, {
										role: 'system',
										content: str
									})
								} catch (e) {
									console.log('解析错误:', e);
								}
							}
						}
					})
				})

			},
			

APP端:使用 renderjs + @microsoft/fetch-event-source

要在 UniApp (Vue2) 的 App 端处理 Server-Sent Events (SSE) 数据流,可以使用 renderjs 结合 @microsoft/fetch-event-source 库。以下是完整的实现方案:

1. 安装依赖

首先安装必要的依赖:

npm install @microsoft/fetch-event-source

2. 添加代码

<template>

			<!-- #ifdef APP -->
			<button :props='mergeProps' :change:props='eventSource.renderBeforeSend' v-show='false'>app端的发送</button>
			<!-- #endif -->
			<button class="send-btn" @click="sendMessage">
				<uni-icons type="paperplane" size="20" color="#fff"></uni-icons>
			</button>

</template>

<script>



		data() {
			return {
				chatId: '', //会话的id
				userInput: '', //初次内容
				userId: JSON.parse(uni.getStorageSync('luxian-store')).user.userInfo.userId, //用户id
				//返回的消息列表数据
				msgList: [],
				isSend: true //是否发送消息
			}
		},



computed: {
			mergeProps() {
				return {
					token: this.token, // 依赖Vuex的token
					isSend: this.isSend, // 依赖组件的isSend
					msgList: this.msgList, // 依赖组件的msgList
					userId: this.userId, // 依赖组件的userId
					id: this.chatId // 依赖组件的id
				}
			}
},


methods: {



			// 获取来自renderjs的消息
			emits({
				str,
				len
			}) {
				this.$set(this.msgList, len, {
					role: 'system',
					content: str
				})
				this.isSend = false;
			},

}

</script>




<script module='eventSource' lang='renderjs'>
	import {
		fetchEventSource
	} from '@microsoft/fetch-event-source';
	export default {
		methods: {
			renderBeforeSend(nVal) {
				let {
					isSend
				} = nVal;
				if (!isSend) return;
				this.handleSSE(nVal);
			},
			handleSSE(nVal) {
				let {
					token,
					msgList,
					userId,
					id
				} = nVal;

				let that = this;
				let len = msgList.length;
				let str = '';

				//1. 设置headers
				const headers = {
					'Content-Type': 'application/json',
				}
				//2. 传递token
				if (token) {
					headers['Authorization'] = token;
				}

				fetchEventSource('https://ai.xuexiluxian.cn/api/xlx-chat/chatMessage/sendMessageSSE', {
					method: 'post',
					headers,
					body: JSON.stringify({
						id: id,
						userId: userId,
						question: msgList.at(-1).content
					}),
					onopen() {
						console.log('sse连接成功');
					},
					onmessage(msg) {
						let {
							data
						} = msg;
						if (data &&
							!data.includes('<br/><br/>tokens') &&
							!data.includes('[DONE]')
						) {
							let parseData = JSON.parse(data);
							str += parseData.content;
							//把render中的str更新到msgList中
							that.$ownerInstance.callMethod('emits', {
								str,
								len
							});
						}
					},
					onclose() {
						console.log('关闭');
					}
				})
			}
		}
	}
</script>
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐