EventSource 接口是 web 内容与服务器发送事件通讯的接口。
一个 EventSource 实例会对 HTTP 服务器开启一个持久化的连接,以 text/event-stream 格式发送事件,此连接会不停保持开启直到通过调用 EventSource.close() 关闭。
EventSource 服务器发送事件是单向的。数据消息只能从服务端发送到客户端。
一、EventSourcePolyfill
EventSourcePolyfill 是EventSource封装的一个方法,EventSourcePolyfill 可以配置请求头
- // 安装
- npm install event-source-polyfill --save
- //引用
- import { EventSourcePolyfill } from "event-source-polyfill";
复制代码 二、直接上代码
- sendRequest(messageId, content, questionId, questionType) {
- const innerIndex = this.messageList.length - 1;
- const aiToken = JSON.parse(localStorage.getItem('token'));
- let that = this;
- let eventSource;
- if (questionId) {
- eventSource = new EventSourcePolyfill(
- `${
- process.env.VUE_APP_WEB_API
- }/url...........?f_rnd=${new Date().getTime()}&message_id=${messageId}&question_id=${questionId}&stream=true`,
- {
- headers: {
- 'Content-Type': 'text/event-stream',
- aiToken: aiToken,
- accept: '*/*',
- 'Cache-Control': 'no-cache',
- Connection: 'keep-alive',
- // 'cache-control': 'max-age=0',
- },
- }
- );
- } else {
- eventSource = new EventSourcePolyfill(
- `${
- process.env.VUE_APP_WEB_API
- }/ai_assistant_chatdoc/receive_message?f_rnd=${new Date().getTime()}&message_id=${messageId}&stream=true`,
- {
- headers: {
- 'Content-Type': 'text/event-stream',
- aiToken: aiToken,
- accept: '*/*',
- 'Cache-Control': 'no-cache',
- Connection: 'keep-alive',
- },
- }
- );
- }
- //open:订阅成功(和后端连接成功)
- eventSource.onopen = function (e) {
- console.log(e, '连接刚打开时触发');
- };
- //message:后端返回信息,格式可以和后端协商
- that.messageQueue = []; //整个流式数据
- this.processing = false; //判断是否返回数据中
- let resultWord = '';
- let rowData = {};
- eventSource.onmessage = function (e) {
- const data = JSON.parse(e.data) || {}; //这里后端返回的是字符串所以目前我这边有转换
- console.log(data, data.data.content, Date.now());
- if (data.code === 200) {
- that.loading = false;
- that.scrollFlag = false;
- if (data.data.content === '[DONE]') { //流式结束了
- rowData = data.data;
- }
- that.messageQueue.push(data.data.content);
- if (that.processing) return;
- that.processing = true;
- (async function processMessages() {
- while (that.processing) {
- // 改为无限循环
- let message;
- if (that.messageQueue.length > 0) {
- message = that.messageQueue.shift();
- if (message === '[DONE]') {
- that.receiveMsg.source = rowData.source;
- that.receiveMsg.sourceEdit = rowData.is_edit;
- that.$set(that.messageList[innerIndex], 'message_id', rowData.message_id);
- that.requestRecomme(messageId, innerIndex);
- } else {
- resultWord += message;
- console.log(resultWord, 'resultWord');
- that.$set(that.messageList, innerIndex, {
- type: 'right',
- session_id: data.data.session_id,
- message_id: data.data.message_id,
- reply_id: data.data.reply_id,
- message: resultWord,
- source: [],
- sourceEdit: [],
- question: [],
- });
- that.receiveMsg = that.messageList[innerIndex];
- that.chcekScroll();
- that.executeScroll(!that.scrollFlag);
- }
- await new Promise(resolve => setTimeout(resolve, 30)); //30毫秒读取一下message
- } else {
- that.processing = false;
- await new Promise(resolve => setTimeout(resolve, 800)); //如果读取速度大于流式返回速度就等一下
- }
- if (that.messageQueue.length === 0 && message === '[DONE]') {
- break;
- }
- }
- that.processing = false;
- })();
- }
- };
- // error:错误(可能是断开,可能是后端返回的信息)
- eventSource.onerror = function (e) {
- console.log(e, '连接无法打开时触发');
- eventSource.close(); // 关闭连接
- setTimeout(() => {}, 5000);
- };
- },
复制代码 链接: https://blog.csdn.net/weixin_49066399/article/details/138713416
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |