当前位置:   article > 正文

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

nodejs sse

前言

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

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

nodejs实现简单的SSE服务

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

  1. const express = require('express');
  2. const app = express();
  3. const port = 8002;
  4. let strArr = [
  5. '所有人,都得死!',
  6. '犯我德邦者,虽远必诛!',
  7. '吾所成之事,不可逆也!',
  8. '一点寒芒先到,随后枪出如龙!',
  9. '我的剑就是你的剑!',
  10. '刀下生,刀下死!'
  11. ]
  12. let setTask = null
  13. app.get('/events', (req, res) => {
  14. res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');
  15. res.setHeader('Cache-Control', 'no-cache');
  16. res.setHeader('Connection', 'keep-alive');
  17. let num = 0
  18. setTask = setInterval(()=>{
  19. res.write(`data:${strArr[num]}\n\n`)
  20. num++
  21. if(num > 5){
  22. res.write(`data:end\n\n`)
  23. res.end()
  24. // res.closed()
  25. clearInterval(setTask)
  26. setTask = null
  27. }
  28. },1000)
  29. });
  30. app.listen(port, () => {
  31. console.log(`${port}端口已启动`);
  32. });

效果如下

 前端实现接收数据流:

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

配置代理(重要)

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

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

  1. devServer:{
  2. client:{
  3. overlay:false
  4. },
  5. port:8080,
  6. open:true,
  7. compress:false, //流式数据返回的关键配置
  8. proxy:{
  9. '/server1':{
  10. target:'http://localhost:3001',
  11. ws:false,
  12. changeOrigin:true,
  13. pathRewrite:{
  14. '^/server1':''
  15. }
  16. },
  17. '/server2':{
  18. target:'http://localhost:3002',
  19. ws:false,
  20. changeOrigin:true,
  21. pathRewrite:{
  22. '^/server2':''
  23. }
  24. },
  25. '/sse':{
  26. target:'http://localhost:8002',
  27. ws:false,
  28. changeOrigin:true,
  29. pathRewrite:{
  30. '^/sse':''
  31. }
  32. }
  33. }
  34. }

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

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

前端实现接口调用
  1. <template>
  2. <div>
  3. <el-button @click="sendMsg">发送消息</el-button>
  4. <p v-for="(item,index) in msgList" :key="index">{{ item }}</p>
  5. </div>
  6. </template>
  7. <script>
  8. export default{
  9. name:'admin',
  10. data(){
  11. return{
  12. msgList:[]
  13. }
  14. },
  15. methods:{
  16. sendMsg(){
  17. let vm = this
  18. //方案1:EventSource
  19. const eventSource = new EventSource('/sse/events');
  20. //消息监听
  21. eventSource.onmessage = function(event) {
  22. console.log(eventSource,vm,'状态')
  23. console.log(event.data); // 输出SSE发送的数据
  24. if(event.data === 'end'){
  25. eventSource.close()
  26. }else{
  27. vm.msgList.push(event.data)
  28. }
  29. };
  30. //连接成功
  31. eventSource.onopen = function(event){
  32. }
  33. //连接出错
  34. eventSource.onerror = function(error) {
  35. if (eventSource.readyState === EventSource.CLOSED) {
  36. // 连接已关闭,可能需要重新连接
  37. console.error('SSE连接已关闭:', error);
  38. }
  39. }
  40. //方案2:xhr(不推荐)
  41. // const xhr = new XMLHttpRequest();
  42. // const url = '/sse/events';
  43. // xhr.open('GET', url,true);
  44. // xhr.setRequestHeader('Accept', 'text/event-stream');
  45. // xhr.onload = (event)=>{
  46. // if(xhr.status === 200){
  47. // console.log(xhr.responseText,'onload',event)
  48. // }
  49. // }
  50. // xhr.onreadystatechange = (event)=>{
  51. // // if(xhr.status === 200){
  52. // // console.log(xhr.responseText,'onreadystatechange',event)
  53. // // }
  54. // }
  55. // xhr.onprogress = (event)=>{
  56. // if(xhr.status === 200){
  57. // console.log(xhr.responseText,'onreadystatechange',event)
  58. // }
  59. // }
  60. // xhr.send()
  61. }
  62. }
  63. }
  64. </script>
  65. <style lang="less">
  66. </style>

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

感觉有用的给个三连吧!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/1003818
推荐阅读
相关标签
  

闽ICP备14008679号