SSE(Server-Sent Events),是一种类似http的协议,实现单向多条消息分段发送的效果,服务器处理完一部分数据会先返回一段数据,等到全部内容发送完成后才会断开连接,我们也可以直接使用http去访问他,但是要等到请求完毕的时候才能一次性收到全部的内容。 打开 chatgpt.com 的控制台可以很清楚地在网络中看到EventStream加载的过程。
在h5中,可以使用 JS的 EventSource接口,但是App中,Uniapp 没有Windows对象,也没有提供SEE的接口,但可以使用RanderJs,RanderJs是一个运行在视图层的js,可以使用完整的JS生态。
SSE标椎是使用GET请求,然而市场上大家基本都使用POST来把参数放到请求体中,所以我使用了github上的一个支持POST的工具fetch-event-source
下面介绍RanderJs怎么使用
使用RanderJs 代码分为3块
前面是标椎的nvue代码
<template><script>
后面的renderjs可以写原生的vue代码。
<script module="renderScript" lang="renderjs">
他们之间的通讯:
- 在视图层依靠:change属性,实现普通script值发生改变调用renderjs中的函数。
<view :change:props="renderScript.handleEnter" :props="props" show="false" id="renderScript"></view>
//:props="props" 绑定普通script中的props变量
//show="false" 隐藏这个标签
//:change:props="renderScript.handleEnter" props属性发生改变执行renderScript中的handleEnter函数
- 使用:change运行的函数会携带多个参数,第三个参数ownerInstance可以调用普通script的代码,值得一提的是,使用ownerInstance.callMethod,请不要使用
<script setup>语法糖,否则调用将失败。
ownerInstance.callMethod('getSseData',参数)
完整代码
<template>
<view :change:props="renderScript.handleEnter" :props="props" show="false" id="renderScript"></view>
<up-input
@confirm="handleEnter"
v-model="content"
placeholder="请填写您的问题"
/>
</template>
<script>
import {onLoad, onShow} from "@dcloudio/uni-app"
import {nextTick, ref, watchEffect} from "vue";
import {chatCategoryEdit, getChat, newChat, sendChat} from "../request/url";
export default {
setup() {
const content = ref('')
const props = ref({})
const handleEnter = () => {
const question = content.value
props.value = {
question: question,
data:{},
token:'xx',
}
}
const getSseData = (data)=>{
console.log(data)
}
return{
content,
props,
handleEnter,
getSseData,
}
}
}
</script>
<script module="renderScript" lang="renderjs">
import {baseUrl} from "../request";
import { fetchEventSource } from '@microsoft/fetch-event-source';
export default {
data(){
return {
}
},
methods:{
handleEnter(newData,oldData,ownerInstance){
if(!newData.data){
return
}
const data = newData.data
const token = newData.token
fetchEventSource(`${baseUrl}/api/chat/chatAi`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token':token
},
body: JSON.stringify(data),
onmessage(ev) {
ownerInstance.callMethod('getSseData',ev)
},
onclose() {
console.log('结束连接');
ownerInstance.callMethod('getSseData',{data:"{"data":"done"}"})
},
onerror(err) {
console.log('发生错误');
console.log(err)
},
async onopen(response) {
console.log('开始连接');
},
});
}
}
}
</script>
这是我来到稀土掘金发的第一篇博客,希望可以帮到大家。