当前位置: 首页 > article >正文

前端处理流式数据(SSE服务)

前言

将数据用流的方式返回给客户端,这种技术需求在传统的管理项目中不多见,但是在媒体或者有实时消息等功能上就会用到,这个知识点对于前端还是很重要的。

即时你不写服务端,但是服务端如果给你这样的接口,你也得知道怎么去使用联调。

nodejs实现简单的SSE服务

SSE服务(Server-Sent Events),是一种服务器向客户端推送实时更新的机制模式。

const express = require('express');  
const app = express();  
const port = 8002;  


let strArr = [
    '所有人,都得死!',
    '犯我德邦者,虽远必诛!',
    '吾所成之事,不可逆也!',
    '一点寒芒先到,随后枪出如龙!',
    '我的剑就是你的剑!',
    '刀下生,刀下死!'
]
let setTask = null
  
app.get('/events', (req, res) => {  
  res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');  
  res.setHeader('Cache-Control', 'no-cache');  
  res.setHeader('Connection', 'keep-alive');  
  let num = 0
  setTask =  setInterval(()=>{
    res.write(`data:${strArr[num]}

`)
    num++
    if(num > 5){
        res.write(`data:end

`)
        res.end()
        // res.closed()
        clearInterval(setTask)
        setTask = null
    }
  },1000)
});  
  
app.listen(port, () => {  
  console.log(`${port}端口已启动`);  
});

效果如下

前端实现接收数据流:

这里使用一个叫做EventSource的api去实现流式接口的调用和数据获取**。**

配置代理(重要)

如果我们用vue,react等等框架开发时,需要在代理处做一些配置,确保数据会以流式的返回。如果不做这层代理的配置,那么你获取的数据就会是执行完所有的res.write,一次性的全部返回给前端,就不是我们想要的效果。

效果如下,在配置代理中将compress设置为false

    devServer:{
      client:{
        overlay:false
      },
      port:8080,
      open:true,
      compress:false,  //流式数据返回的关键配置
      proxy:{
        '/server1':{
          target:'http://localhost:3001',
          ws:false,
          changeOrigin:true,
          pathRewrite:{
            '^/server1':''
          }
        },
        '/server2':{
          target:'http://localhost:3002',
          ws:false,
          changeOrigin:true,
          pathRewrite:{
            '^/server2':''
          }
        },
        '/sse':{
          target:'http://localhost:8002',
          ws:false,
          changeOrigin:true,
          pathRewrite:{
            '^/sse':''
          }
        }
      }
    }

之前没有配置这里,导致数据一直是一次性返回的,困了我一会,后来查找原因,借鉴的这篇文章

fetchEventSource请求,数据没有流式输出_vue2 eventsource为什么没有流式输出-CSDN博客

前端实现接口调用
<template>
    <div>
        <el-button @click="sendMsg">发送消息</el-button>
        <p v-for="(item,index) in msgList" :key="index">{{ item }}</p>
    </div>
   
  </template>
  <script>
   export default{
      name:'admin',
      data(){
        return{
            msgList:[]
        }
      },
      methods:{
    sendMsg(){
        let vm = this

    //方案1:EventSource
      const eventSource = new EventSource('/sse/events');  
  //消息监听
  eventSource.onmessage = function(event) {  
    console.log(eventSource,vm,'状态')
    console.log(event.data); // 输出SSE发送的数据  
    if(event.data === 'end'){
      eventSource.close()
    }else{
      vm.msgList.push(event.data)
    }
 
  };  
  //连接成功
  eventSource.onopen = function(event){

  }
  //连接出错
  eventSource.onerror = function(error) {  
    if (eventSource.readyState === EventSource.CLOSED) {  
      // 连接已关闭,可能需要重新连接  
      console.error('SSE连接已关闭:', error);  
    }  
  }

  //方案2:xhr(不推荐)
  // const xhr = new XMLHttpRequest(); 
  // const url = '/sse/events'; 
  // xhr.open('GET', url,true); 
  // xhr.setRequestHeader('Accept', 'text/event-stream');

  // xhr.onload = (event)=>{
  //   if(xhr.status === 200){
  //     console.log(xhr.responseText,'onload',event)
  //   }
  // }

  // xhr.onreadystatechange = (event)=>{
  //   // if(xhr.status === 200){
  //   //   console.log(xhr.responseText,'onreadystatechange',event)
  //   // }
    
  // }
  // xhr.onprogress = (event)=>{
  //   if(xhr.status === 200){
  //     console.log(xhr.responseText,'onreadystatechange',event)
     
  //   }
  // }
  // xhr.send()
    }
      }
   }
  </script>
  <style lang="less">
  </style>

这样就大功告成了,如果以后要是做类似于chatgpt这种效果,就可以用到的。

感觉有用的给个三连吧!


http://www.kler.cn/a/447205.html

相关文章:

  • FPGA:FPGA器件选型
  • go-zero(十四)实践:缓存一致性保证、缓存击穿、缓存穿透与缓存雪崩解决方案
  • css常用属性有哪些
  • 【GCC】2015: draft-alvestrand-rmcat-congestion-03 机器翻译
  • InternVL简读
  • WebSocket入门与结合redis
  • 单北斗+鸿蒙系统+国产芯片,遨游防爆手机自主可控“三保险”
  • 基于预测反馈的情感分析情境学习
  • 国内网络在Ubuntu 22.04中在线安装Ollama并配置Open-WebuiDify
  • 【论文阅读】Computing the Testing Error without a Testing Set
  • MySQL 中的 MVCC:实现高效并发控制
  • 重拾设计模式--观察者模式
  • R语言函数简介
  • [SZ901]JTAG高速下载设置(53Mhz)
  • C# 6.0 连接elasticsearch数据库
  • 【进阶编程】MVVM框架的每层对应那些业务
  • 前端(Vue)tagsView(子标签页视图切换) 原理及通用解决方案
  • ubuntu 卸载 MySQL
  • EJB(Enterprise JavaBean)和JavaBean
  • Postbot使用教程
  • Springboot提供外部接口和访问外部接口的简单例子
  • qwt 之 QwtPlotPicker
  • Docker_常用命令详解
  • 嵌入式驱动开发详解19(regmap驱动架构)
  • CTF知识集-SSRF
  • 组件十大传值