如何提前终止EventSource事件源监听器以响应新的用户请求
解决方案
你现有代码已经封装了close的清理逻辑,只需要把清理函数的引用提前存下来,每次发起新请求前优先执行上一次的清理逻辑即可,具体修改如下:
第一步:在上层作用域声明持久化变量
在全局作用域、组件顶层作用域等不会被单次请求重置的位置声明两个变量,用来存储当前活跃的EventSource实例和对应的清理函数,避免旧实例引用被覆盖后无法关闭:
let activeEventSource = null let clearPrevListener = null // 额外存上一次请求的id,方便移除对应事件监听 let lastRequestId = null
第二步:新请求发起前先清理旧连接
每次用户触发新的下载请求时,先判断有没有未关闭的旧连接,优先执行清理:
// 新请求发起前执行 if (clearPrevListener && activeEventSource) { // 调用之前返回的清理函数关闭连接 clearPrevListener() // 额外移除对应id的事件监听,避免内存泄漏 activeEventSource.removeEventListener(`progress${lastRequestId}`, updateMp4Data) // 重置变量 activeEventSource = null clearPrevListener = null lastRequestId = null }
第三步:调整现有初始化逻辑,存储新实例的引用
修改你现有的EventSource初始化代码,把新实例和清理函数存到上面声明的变量里:
// 新请求初始化 lastRequestId = id activeEventSource = new EventSource(`/${id}/mp4Event`); function getVidProgress () { activeEventSource.addEventListener(`progress${id}`, updateMp4Data); return () => activeEventSource.close(); }; // 存储清理函数 clearPrevListener = getVidProgress()
额外注意事项
- 下载任务正常结束(成功/失败)时也要主动调用
clearPrevListener清理连接,EventSource默认会在连接断开后自动重试,不主动关闭会产生无用的后台请求 - 如果是单页应用,用户离开当前页面时也要执行清理逻辑,避免内存泄漏
内容的提问来源于stack exchange,提问作者Kram Retnart
相关产品推荐
相关产品推荐

