插件窝 干货文章 如何使用fetchEventSource实现sse流式请求

如何使用fetchEventSource实现sse流式请求

class fetchEventSource 数据 abortController 101    来源:    2024-10-30

使用fetchEventSource实现sse流式请求

最近在项目开发的过程中,需要实现一个功能

根据进度条的进度动态实时加载获取到的数据并展示出来

用到的是fetchEventSource

以下主要写下js的实现的过程(前端用到的ui组件是antd-design-vue1.78版本 vue2.0项目)

首先下载插件:

npm install --save @microsoft/fetch-event-source

<div class="progress_container" v-if="!progressDone">
        <div class="progress_row">
          <a-progress type="line" :percent="progressValue" status="active" />
        </div>
        <div class="progress_text">
          {{ progressTxt }}
        </div>
</div>


<script>
  import { fetchEventSource } from '@microsoft/fetch-event-source'
  import storage from 'store'
  import { ACCESS_TOKEN } from '@/store/mutation-types'
   export default {
        data () {
          return {
            speed: 30,
            progressValue: 0,//进度条初始值
            progressTxt: '',//进度条文字展示默认值
            eventSource: null,
            abortController: null,
            checkMessage: [],
            checkResult: {},
            resultData: [],
            submitUnable: true,
            progressDone: false
          }
        },
      created () {
        this.connectSSE()
      },
      destroyed () {
          this.stopSSE()
      },
      methods: {
        connectSSE () {
          this.abortController = new AbortController() // 终止or结束会话,做了个全局的...
          const url = process.env.VUE_APP_API_BASE_URL + `自己的请求数据接口`
          const token = storage.get(ACCESS_TOKEN)
          // 开始会话链接,也做了个全局的......
          this.eventSource = fetchEventSource(url, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              [ACCESS_TOKEN]: token
            },
            // 传参只能发送文本格式的数据
            body: JSON.stringify({
           
            }),
            signal: this.abortController.signal,
            onopen: (event) => {
              console.log(event, 'SSE在连接打开时被调用')
            },
            onmessage: (event) => {
              // console.log('SSE会在通过事件源收到数据时触发')
              // console.log('接口返回', JSON.parse(event.data))
              //我这里是判断我请求回来的数据里是否包含'[DONE]',他是数组里的最后一项,表示加载完成
              if (!event.data.includes('[DONE]')) {
                const data = JSON.parse(event.data)
                const text = data.message
                const percent = data.percent
                const message = data.message
                if (text === 'connect') {
                  // 连接成功,开始检测逻辑
                  this.progressDone = false
                  this.progressValue = 0
                  this.progressTxt = '数据检查中,该过程可能需要一段时间,请勿关闭窗口'
                
                  this.getTurnCheck()
                 return false
                }
                //定时器,控制进度条和文字的展示速度
                this.speed += 300
                this.timer = setTimeout(() => {
                  this.progressValue = Number(percent)
                  this.progressTxt = message
                  if (this.progressValue === 100 && !this.progressDone) {
                 
                    this.stopSSE()
                  }
                }, this.speed)
              }
              
              if (event.data.includes('[DONE]')) {
              }
              
            },
            onerror: () => {
              console.log('SSE抛出异常onerror')
              this.stopSSE()
            },
            // onclose函数是会话结束正常关闭触发,但几乎没有做到这步,不执行这个回调,不知道什么原因
            onclose: () => {
              console.log('onclose') 
            }
          })
        },
        // 停止SSE
        async stopSSE () {
          // 关闭业务,执行关闭sse数据接口
          await this.getCloseSse()
          if (this.abortController) {
            this.timer && clearTimeout(this.timer)
            console.log('SSE结束会话了')
            this.abortController.abort() // 结束会话
          }
        },
        //检查数据的接口
        async getTurnCheck () {
          const params = {
            
          }
      
        },
        //关闭sse接口
        async getCloseSse () {
          const params = {
            
          }
          const [err, res] = await to(closeSse(params))
          if (err) return false
        }

      },


    }
</script>

总结

以上为个人经验,希望对您有所帮助。