跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
|注册
博客列表

目录

  1. JavaScript 实现 HTTPS SSE 连接
  2. 一、SSE 简介
  3. 二、SSE 客户端代码
  4. 三、使用示例(Vue3/Vite 集成)
  5. 3.1 全局引入(main.js)
  6. 3.2 组件内使用(页面/组件中)
  7. 3.3 其他集成建议
  8. 3.4 特殊场景处理
  9. 四、HTTPS 适配注意事项
  10. 五、后端配合要求
  11. 六、常见问题排查
  12. 七、拓展方向
JavaScript大前端

JavaScript 实现 HTTPS SSE 连接

本文介绍如何在 JavaScript 中实现支持 HTTPS 的 Server-Sent Events (SSE) 连接。内容包括 SSE 客户端封装(自动重连、事件监听、单例模式)、Vue3/Vite 项目集成示例、Token 刷新与用户切换处理、HTTPS 环境下的证书与跨域配置,以及后端响应头规范。通过该方案可实现实时通知、消息提醒等单向通信场景,并提供常见问题排查指南。

墨染流年发布于 2026/3/29更新于 2026/4/131 浏览

JavaScript 实现 HTTPS SSE 连接

一、SSE 简介

SSE(Server-Sent Events,服务器推送事件)是一种基于 HTTP 的单向通信协议,允许服务器主动向客户端推送数据,适用于实时通知、消息提醒、状态同步等场景。与 WebSocket 双向通信不同,SSE 仅支持服务器到客户端的单向传输,开销更小,适配 HTTPS 协议更简洁。

本文实现的 SSE 客户端具备以下特性:HTTPS 适配、自动重连、事件监听、单例模式、错误处理、动态拼接用户参数,可直接集成到 Vue3/Vite 等前端项目中。

二、SSE 客户端代码

核心文件:utils/sseClient.js,采用类封装,提供完整的连接、监听、断开、重连能力,支持自定义事件与参数动态拼接。

import { getToken, getUserInfo } from '@/utils/tools';

class SSEClient {
  constructor() {
    this.source = null; // SSE 核心实例
    // 基础 URL(从环境变量读取,适配不同环境)
    this.baseUrl = import.meta.env.VITE_API_BASE_URL;
    this.path = '/sse/talent/adminConnect'; // SSE 接口路径
    this.url = `${this.baseUrl}${this.path}`;
    // 请求头(携带 Token 做权限校验,适配 HTTPS 鉴权),目前这种方式并不支持自定义 headers
    this.headers = {
      satoken: getToken(),
    };
    this.reconnectInterval = 30000; // 自动重连间隔(30 秒,可配置)
    this.isConnected = ; 
    . = ; 
    . =  (); 
    . = ; 
    . = ; 
  }

  
  () {
     {
       userInfo = (); 
       (!userInfo || !userInfo.) {
         .;
      }
       userId = userInfo.; 
       params =  ();
      params.(, userId);
      
       fullUrl = ;
       fullUrl;
    }  (error) {
      .(, error);
       .;
    }
  }

  
  () {
    
     (. || .) {
      ;
    }
    
     withCredentials = options. || ;
    . = options. || .;
    
    .();
    
    . = .();
     {
      
       eventSourceInitDict = { withCredentials };
      . =  (., eventSourceInitDict);
      
      .. =  {
        . = ;
        . = ;
        . = ; 
        .(, { : , : . });
        .(, .);
      };
      
      .. =  {
         {
          
           data = .(event.);
          .(, data);
        }  (e) {
          
          .(, event.);
        }
      };
      
      .. =  {
        . = ;
         errorMsg = ;
        .(errorMsg, error);
        .(, { : errorMsg, error, : .. });
        
         (.. === . && !.) {
          .++;
          
           (. > .) {
            . = ;
            .(, { : . });
            .();
            ;
          }
          . = ;
          .();
          
          ( {
            .(options);
          }, .);
        }
      };
      
      ..( {
        .(eventName, handler);
      });
    }  (e) {
      . = ;
       errorMsg = ;
      .(errorMsg, e);
      .(, { : errorMsg, : e });
    }
  }

  
  () {
    
     systemEvents = [, , ];
     (systemEvents.(eventName)) ;
    
     (.) {
      ..(eventName, handler);
      
      ..(eventName,  {
         {
           data = .(event.);
          (data);
        }  (e) {
          (event.);
        }
      });
    }
  }

  
  () {
     ( handler !== ) {
      .();
      ;
    }
    
    ..(eventName, handler);
    
     (. && .) {
      .(eventName, handler);
    }
  }

  
  () {
     handler = ..(eventName);
     (handler) {
       {
        (data);
      }  (e) {
        .(, e);
      }
    }
  }

  
  () {
    ..(eventName);
     (.) {
       handler = ..(eventName);
       (handler) {
        ..(eventName, handler);
      }
    }
  }

  
  () {
     (.) {
      ..();
      . = ;
    }
    
    . = ;
    . = ;
     (isManual) {
      . = ; 
      .(, { isManual });
      .();
    }
  }

  
  () {
    . = ;
    . = ;
    .(options);
  }

  
  () {
    . = .();
    
     (.) {
      .();
    }
  }
}


  sseClient =  ();
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog

更多推荐文章

查看全部
  • 基于 Spring Boot 与 MySQL 的仓库管理系统设计与实现
  • Visual C++ 运行库一体化解决方案
  • Spring Boot 条件注解全解析:核心机制与使用场景
  • Java 多线程核心:线程与进程区别、创建方式及线程安全
  • Linux 系统安装 MATLAB 完整指南:下载、配置与启动
  • pxcharts-vue:基于 Vue3 的开源多维表格解决方案
  • GitHub 镜像加速:Gitee 与 Coding 开源项目克隆指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

false
// 连接状态标识
this
isReconnecting
false
// 重连状态标识(避免重复重连)
this
eventHandlers
new
Map
// 事件处理器映射表(支持多事件)
this
maxReconnectTimes
10
// 最大重连次数(避免无限重连)
this
reconnectCount
0
// 当前重连次数
/** * 动态拼接 URL * 避免重复拼接相同参数,异常时返回基础 URL */
getUrlWithParams
try
const
getUserInfo
// 无用户信息时返回基础 URL
if
userId
return
this
url
const
userId
// 拼接参数
const
new
URLSearchParams
append
'userId'
// 拼接完整 URL,避免重复参数
const
`${this.url}?${params.toString()}`
return
catch
console
warn
'SSE 拼接参数失败,使用基础 URL:'
return
this
url
/** * 初始化 SSE 连接 * @param {Object} options - 配置项 * @param {boolean} options.withCredentials - 是否携带跨域凭证 * @param {number} options.reconnectInterval - 自定义重连间隔 */
connect
options = {}
// 避免重复连接或重连中重复触发
if
this
isConnected
this
isReconnecting
return
// 合并配置项(支持自定义重连间隔)
const
withCredentials
false
this
reconnectInterval
reconnectInterval
this
reconnectInterval
// 先断开已有连接(防止残留连接)
this
disconnect
// 更新最新 URL(确保参数实时)
this
url
this
getUrlWithParams
try
// SSE 初始化配置(适配 HTTPS 与跨域)
const
this
source
new
EventSource
this
url
// 监听连接成功事件
this
source
onopen
() =>
this
isConnected
true
this
isReconnecting
false
this
reconnectCount
0
// 重置重连次数
this
emit
'open'
status
'connected'
url
this
url
console
log
'SSE 连接成功:'
this
url
// 监听服务器推送的通用消息
this
source
onmessage
(event) =>
try
// 尝试解析 JSON 格式数据(兼容字符串与 JSON)
const
JSON
parse
data
this
emit
'message'
catch
// 非 JSON 格式直接返回原始数据
this
emit
'message'
data
// 监听连接错误(核心:错误处理与自动重连)
this
source
onerror
(error) =>
this
isConnected
false
const
`SSE 连接错误(状态码:${this.source.readyState})`
console
error
this
emit
'error'
message
readyState
this
source
readyState
// 仅在连接关闭时触发重连(排除临时错误)
if
this
source
readyState
EventSource
CLOSED
this
isReconnecting
this
reconnectCount
// 超过最大重连次数停止重连
if
this
reconnectCount
this
maxReconnectTimes
this
isReconnecting
false
this
emit
'reconnect-failed'
maxTimes
this
maxReconnectTimes
console
error
`SSE 重连失败(已超过最大次数 ${this.maxReconnectTimes})`
return
this
isReconnecting
true
console
log
`SSE 准备重连(第 ${this.reconnectCount}/${this.maxReconnectTimes} 次),间隔 ${this.reconnectInterval}ms`
// 延迟重连(避免频繁请求)
setTimeout
() =>
this
connect
this
reconnectInterval
// 注册已绑定的自定义事件(避免重连后事件丢失)
this
eventHandlers
forEach
(handler, eventName) =>
this
bindCustomEvent
catch
this
isReconnecting
false
const
'创建 SSE 连接失败(初始化异常)'
console
error
this
emit
'error'
message
error
/** * 绑定自定义事件(抽离复用,适配重连场景) * @param {string} eventName - 自定义事件名 * @param {Function} handler - 事件处理器 */
bindCustomEvent
eventName, handler
// 排除系统内置事件(open/message/error)
const
'open'
'message'
'error'
if
includes
return
// 移除已有监听(避免重复绑定)
if
this
source
this
source
removeEventListener
// 绑定新监听
this
source
addEventListener
(event) =>
try
const
JSON
parse
data
handler
catch
handler
data
/** * 注册事件监听(支持系统事件与自定义事件) * @param {string} eventName - 事件名 * @param {Function} handler - 事件处理器 */
on
eventName, handler
if
typeof
'function'
console
warn
`SSE 事件 ${eventName} 处理器必须是函数`
return
// 存储事件处理器
this
eventHandlers
set
// 已连接状态下立即绑定事件
if
this
source
this
isConnected
this
bindCustomEvent
/** * 触发事件(供内部调用,分发消息) * @param {string} eventName - 事件名 * @param {any} data - 事件数据 */
emit
eventName, data
const
this
eventHandlers
get
if
try
handler
catch
console
error
`SSE 触发事件 ${eventName} 失败:`
/** * 移除事件监听 * @param {string} eventName - 事件名 */
off
eventName
this
eventHandlers
delete
if
this
source
const
this
eventHandlers
get
if
this
source
removeEventListener
/** * 关闭 SSE 连接(重置状态,避免内存泄漏) * @param {boolean} isManual - 是否手动关闭(区别于异常断开) */
disconnect
isManual = false
if
this
source
this
source
close
this
source
null
// 重置状态
this
isConnected
false
this
isReconnecting
false
if
this
reconnectCount
0
// 手动关闭重置重连次数
this
emit
'close'
console
log
'SSE 手动关闭连接'
/** * 强制重连(主动触发重连,重置重连次数) * @param {Object} options - 配置项 */
forceReconnect
options = {}
this
reconnectCount
0
this
isReconnecting
false
this
connect
/** * 更新连接参数(如 Token 过期后刷新 URL) */
updateParams
this
url
this
getUrlWithParams
// 已连接状态下重新连接(刷新参数)
if
this
isConnected
this
forceReconnect
// 全局单例模式(确保全项目唯一 SSE 实例,避免多连接冲突)
export
const
new
SSEClient

三、使用示例(Vue3/Vite 集成)

3.1 全局引入(main.js)

将 SSE 实例挂载到全局,便于全项目使用:

import { createApp } from 'vue';
import App from './App.vue';
import { sseClient } from '@/utils/sseClient';

const app = createApp(App);
// 全局挂载 SSE 实例
app.config.globalProperties.$sse = sseClient;
app.mount('#app');
3.2 组件内使用(页面/组件中)
<script setup>
import { onMounted, onUnmounted } from 'vue';
import { sseClient } from '@/utils/sseClient';

onMounted(() => {
  // 1. 注册事件监听
  // 连接成功事件
  sseClient.on('open', (res) => {
    console.log('SSE 连接成功', res);
    // 可在这里处理连接成功后的逻辑(如更新 UI 状态)
  });
  // 通用消息事件(服务器推送的所有消息)
  sseClient.on('message', (data) => {
    console.log('收到 SSE 消息', data);
    // 处理业务逻辑(如实时通知、数据更新)
  });
  // 自定义事件(后端指定事件名,如"notice")
  sseClient.on('notice', (data) => {
    console.log('收到自定义通知', data);
    // 处理自定义消息(如系统通知、业务提醒)
  });
  // 错误事件
  sseClient.on('error', (err) => {
    console.error('SSE 异常', err);
    // 处理错误(如提示用户、降级处理)
  });
  // 重连失败事件
  sseClient.on('reconnect-failed', (res) => {
    console.error('SSE 重连失败', res);
    // 提示用户手动刷新页面
  });
  // 2. 启动 SSE 连接(配置跨域凭证)
  sseClient.connect({ withCredentials: true });
});

onUnmounted(() => {
  // 组件卸载时移除事件监听、关闭连接(避免内存泄漏)
  sseClient.off('open');
  sseClient.off('message');
  sseClient.off('notice');
  sseClient.off('error');
  sseClient.off('reconnect-failed');
  sseClient.disconnect(true); // 手动关闭连接
});
</script>
3.3 其他集成建议
  • 可以用 Pinia 全局管理并调用,配合路由守卫也可以全局使用。
3.4 特殊场景处理
  1. Token 过期刷新:Token 刷新后调用 sseClient.updateParams(),自动更新 URL 并重新连接。
  2. 用户切换:切换用户时先调用 sseClient.disconnect(true) 关闭连接,再调用 connect() 重新连接。
  3. 手动触发重连:需要主动重连时调用 sseClient.forceReconnect()。

四、HTTPS 适配注意事项

  • SSE 基于 HTTP/HTTPS 协议,HTTPS 环境下需确保后端 SSE 接口配置正确的 SSL 证书,避免证书无效导致连接失败。
  • 请求头鉴权:HTTPS 场景下建议将 Token 放在 URL 参数或请求头中(本文采用 URL 参数,适配部分后端不支持 SSE 自定义请求头的场景)。
  • 跨域配置:若前端与后端跨域,需后端配置 CORS 允许 EventSource 请求,同时前端开启 withCredentials: true 携带跨域凭证。
  • 连接超时:SSE 无内置超时机制,可通过后端设置心跳消息(如每 30 秒推送一次空消息),前端监听心跳判断连接状态。

五、后端配合要求

  1. 响应头配置:后端需返回正确的 SSE 响应头 Content-Type: text/event-stream,同时设置 Cache-Control: no-cache 禁止缓存。
  2. 消息格式:后端推送消息需遵循 SSE 格式规范,如 data: { "msg": "hello" }\n\n(注意结尾双换行)。
  3. 自定义事件:后端推送自定义事件时需指定事件名,如 event: notice\ndata: { "msg": "通知" }\n\n。
  4. 连接保持:后端需保持 SSE 连接长驻,避免主动断开,同时处理客户端断开后的资源释放。

六、常见问题排查

  1. 连接失败(403 无权限):检查 Token 是否有效、用户 ID 是否正确,后端是否对 SSE 接口做了权限校验。
  2. 重连频繁触发:排查后端是否主动断开连接、网络是否不稳定,可调整 reconnectInterval 重连间隔。
  3. 消息无法解析:检查后端推送消息格式是否符合 SSE 规范,是否为合法 JSON(非 JSON 格式会走字符串解析分支)。
  4. 跨域错误:协调后端配置 CORS,允许前端域名访问,同时前端开启 withCredentials 配置。
  5. 内存泄漏:组件卸载时必须移除事件监听并关闭连接,避免残留实例导致内存泄漏。

七、拓展方向

  1. 添加日志记录:集成日志工具,记录 SSE 连接状态、消息内容、错误信息,便于线上问题排查。
  2. 心跳检测:前端定时发送心跳请求(或后端定时推送心跳),实现连接状态精准判断。
  3. 多实例支持:修改单例模式为工厂模式,支持同时创建多个 SSE 实例,适配多接口推送场景。
  4. TypeScript 适配:添加类型定义,提升代码提示与类型安全,适配 TS 项目。
  5. 失败重试策略:支持指数退避重连(重连间隔逐渐延长),减少后端压力。
  • RabbitMQ 技术指南(C/C++版)
  • Python RPA+ 爬虫:模拟人工操作采集 ERP 系统数据(金蝶/用友无接口)
  • Python 异步爬虫:基于 aiohttp 与 asyncio 的图片批量下载器
  • Python 字节码逆向工具 pycdc 使用指南与原理分析
  • 基于 AI Studio 构建自定义爬虫方案
  • IDEA 下载 JDK 慢的真相:权限、DNS 与 CDN 解析
  • Visual C++运行库缺失导致程序启动失败解决方案
  • Whisper 语音识别模型下载指南:版本选择与格式说明
  • 腾讯突然出手!QClaw 内测上线:用微信就能操控电脑,对标 OpenClaw 的 AI Agent 它来啦
  • SSH 密钥交换算法安全加固与 CVE-2002-20001 修复指南
  • Java 自旋锁与读写锁详解
  • 基于 JeecgBoot 低代码平台构建请假审批系统实战
  • Copilot Plan Mode 与多模型协同实战:复杂项目开发实践