使用 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>

~~完结

<think>好的,我现在需要解决用户的问题:如何主动中断FetchEventSource请求,并给出示例代码。首先,我得回忆一下FetchEventSource的相关知识。 用户提到了使用AbortController来中断fetch请求,这可能也适用于FetchEventSource。因为FetchEventSource通常基于fetch API,所以可能支持类似的机制。根据引用[2],AbortController确实可以用来中断fetch请求,所以或许同样的方法适用。 接下来,我需要确认FetchEventSource是否接受signal参数。查阅文档或相关资料,发现FetchEventSource的配置参数中有一个signal选项,可以传入AbortController的signal。这样,当调用abort()时,请求就会被中断。 然后,考虑如何在代码中实现。首先创建AbortController实例,然后在调用fetchEventSource时,将signal配置进去。当需要中断时,调用abort()方法即可。这样应该能中断请求。 另外,用户提供的引用[3]中提到通过dispatch action来取消请求,这可能是在React或Redux中的用法,但核心还是使用AbortController。所以示例代码应该展示如何正确使用AbortController和FetchEventSource结合。 需要注意的是,在请求过程中处理错误,特别是当abort被触发时,需要捕获错误并处理。例如,在onopen或onmessage中检查是否已经abort,或者监听abort事件。 最后,确保代码示例正确,包括必要的导入或引用,以及正确的语法。例如,如果使用JavaScript或TypeScript,可能需要引入fetchEventSource库,如@microsoft/fetch-event-source。 总结步骤: 1. 创建AbortController实例。 2.fetchEventSource的配置中包含signal。 3. 在需要中断时调用abort()。 4. 处理中断后的清理或错误捕获。 现在将这些步骤转化为具体的代码示例,并解释每一步的作用。同时,引用相关的参考资料,如引用[2]和引用[3],来支持方法的正确性。</think>以下是主动中断FetchEventSource请求的解决方案和示例代码: ### 一、实现原理 通过结合AbortController和FetchEventSource的signal参数实现请求中断。当调用$abortController.abort()$时,会触发请求中断[^2]。 ### 二、具体步骤 1. 创建AbortController实例 2. 将signal参数传入fetchEventSource配置 3. 在需要中断时调用abort方法 ### 三、示例代码 ```javascript import { fetchEventSource } from '@microsoft/fetch-event-source'; // 创建中断控制器 const abortController = new AbortController(); async function fetchData() { try { await fetchEventSource('/api/stream', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TOKEN' // 解决请求头验证问题[^1] }, signal: abortController.signal, // 绑定中断信号 openWhenHidden: true, // 保持后台连接 onopen(response) { if (response.ok) return; throw new Error(`HTTP error ${response.status}`); }, onmessage(event) { console.log('Received data:', event.data); }, onerror(err) { throw err; // 必须抛出以保持流式连接 } }); } catch (err) { if (err.name === 'AbortError') { console.log('Request was aborted'); } else { console.error('Request failed:', err); } } } // 主动中断请求 function cancelRequest() { abortController.abort(); // 触发请求中断[^2][^3] console.log('SSE connection terminated'); } ``` ### 四、关键点说明 1. **AbortController集成**:通过signal参数将控制器与请求绑定 2. **错误处理**:需要捕获AbortError类型错误进行特殊处理 3. **状态管理**:建议结合Redux等状态管理工具进行请求生命周期管理 4. **连接保持**:通过$openWhenHidden: true$保持浏览器后台连接[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值