wujingjing
2025-01-14 12a89593d13fa38810c7af54c7ea8cb72ae65a10
src/utils/sse/SSEClient.ts
@@ -1,16 +1,18 @@
import type { AxiosRequestConfig } from 'axios';
import { accessSessionKey } from '../request';
import { SESSION_KEY } from '../request';
import { Local } from '../storage';
import { debounce } from 'lodash-es';
export interface SSEOptions {
   /** 重试次数 */
   retries?: number;
   /** 重试延迟(ms) */
   retryDelay?: number;
   /** 超时时间(ms) */
   timeout?: number;
   /** 请求配置 */
   // requestConfig?: AxiosRequestConfig;
   /** 是否自动重连 */
   autoReconnect?: boolean;
   /** 请求头 */
   headers?: Record<string, string>;
}
export interface SSEEventCallbacks {
@@ -23,23 +25,23 @@
   /** 连接关闭回调 */
   onClose?: () => void;
   /** 重试回调 */
   onRetry?: (retryCount: number) => void;
   onRetry?: () => void;
}
export class SSEClient {
   private eventSource: EventSource | null = null;
   private retryCount = 0;
   private isConnecting = false;
   private reconnectTimeout: number | null = null;
   private abortController: AbortController | null = null;
   constructor(private url: string, private options: SSEOptions = {}, private callbacks: SSEEventCallbacks = {}) {
      // 设置默认值
      this.options = {
         retries: 3,
         retryDelay: 1000,
         timeout: 30000,
         autoReconnect: true,
         timeout: 3000,
         headers: {
            [SESSION_KEY]: Local.get(accessSessionKey),
         },
         ...options,
      };
   }
@@ -48,36 +50,20 @@
    * 建立连接
    */
   async connect(params?: Record<string, any>): Promise<void> {
      if (this.isConnecting) return;
      this.isConnecting = true;
      try {
         // 构建 URL 和参数
         const queryString = params ? `?${new URLSearchParams(params).toString()}` : '';
         const queryString = params && Object.values(params).length ? `?${new URLSearchParams(params).toString()}` : '';
         const fullUrl = `${this.url}${queryString}`;
         // 创建 AbortController 用于超时控制
         this.abortController = new AbortController();
         // 设置超时
         const timeoutId = setTimeout(() => {
            this.abortController?.abort();
            throw new Error('Connection timeout');
         }, this.options.timeout);
         // 创建 EventSource
         // this.abortController = new AbortController();
         // 创建 EventSource 并添加 headers
         this.eventSource = new EventSource(fullUrl);
         // 清除超时
         clearTimeout(timeoutId);
         // 绑定事件处理
         this.bindEvents();
         this.isConnecting = false;
      } catch (error) {
         this.isConnecting = false;
         await this.handleError(error);
         console.log('catch error');
      }
   }
@@ -88,6 +74,7 @@
      if (!this.eventSource) return;
      this.eventSource.onopen = () => {
         console.log('连接成功');
         this.callbacks.onOpen?.();
      };
@@ -107,7 +94,6 @@
      };
      this.eventSource.onerror = async (error) => {
         await this.handleError(error);
      };
   }
@@ -116,23 +102,19 @@
    */
   private async handleError(error: any): Promise<void> {
      this.callbacks.onError?.(error);
      if (this.options.autoReconnect && this.retryCount < (this.options.retries || 0)) {
         // debugger;
         this.retryCount++;
         this.callbacks.onRetry?.(this.retryCount);
      if (this.options.autoReconnect) {
         this.callbacks.onRetry?.();
         // 延迟重试
         await new Promise((resolve) => {
            this.reconnectTimeout = setTimeout(resolve, this.options.retryDelay);
         });
         // 重新连接
         await this.connect();
      } else {
         this.disconnect();
      }
   }
   /**
    * 断开连接
@@ -142,20 +124,17 @@
         clearTimeout(this.reconnectTimeout);
         this.reconnectTimeout = null;
      }
      if (this.eventSource) {
         this.eventSource.close();
         this.eventSource = null;
      }
      if (this.abortController) {
         this.abortController.abort();
         this.abortController = null;
      }
      // if (this.abortController) {
      //    this.abortController.abort();
      //    this.abortController = null;
      // }
      this.isConnecting = false;
      this.callbacks.onClose?.();
      this.retryCount = 0;
   }
   /**