浏览器网络请求 API:全面解析与高级封装(1)

引言

在现代Web开发中,网络请求是实现前后端数据交互的核心技术。从基础的XMLHttpRequest到现代的Fetch API,再到功能丰富的WebSocket,浏览器提供了多种网络通信机制。本文将全面深入探讨浏览器网络请求相关的API,提供高级封装方案,并涵盖实际开发中的各种复杂场景。

一、现代网络请求API概览

1.1 从XMLHttpRequest到Fetch API
javascript 复制代码
class NetworkAPIEvolution {
  // 传统的XMLHttpRequest实现
  static xhrRequest(url, options = {}) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      const {
        method = 'GET',
        headers = {},
        data = null,
        timeout = 0,
        responseType = ''
      } = options;
      
      xhr.open(method, url, true);
      
      // 设置请求头
      Object.entries(headers).forEach(([key, value]) => {
        xhr.setRequestHeader(key, value);
      });
      
      // 设置响应类型
      if (responseType) {
        xhr.responseType = responseType;
      }
      
      // 设置超时
      xhr.timeout = timeout;
      
      // 事件处理
      xhr.onload = function() {
        if (xhr.status >= 200 && xhr.status < 300) {
          let response;
          
          try {
            if (xhr.responseType === 'json') {
              response = xhr.response;
            } else if (xhr.responseType === 'blob') {
              response = xhr.response;
            } else {
              response = JSON.parse(xhr.responseText);
            }
          } catch (e) {
            response = xhr.responseText;
          }
          
          resolve({
            data: response,
            status: xhr.status,
            statusText: xhr.statusText,
            headers: xhr.getAllResponseHeaders()
          });
        } else {
          reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));
        }
      };
      
      xhr.onerror = function() {
        reject(new Error('Network error'));
      };
      
      xhr.ontimeout = function() {
        reject(new Error('Request timeout'));
      };
      
      xhr.onprogress = function(event) {
        if (event.lengthComputable) {
          const percentComplete = (event.loaded / event.total) * 100;
          console.log(`Upload progress: ${percentComplete.toFixed(2)}%`);
        }
      };
      
      xhr.send(data);
    });
  }
  
  // Fetch API基础实现
  static async fetchRequest(url, options = {}) {
    const {
      method = 'GET',
      headers = {},
      body = null,
      timeout = 30000,
      credentials = 'same-origin',
      mode = 'cors',
      cache = 'default',
      redirect = 'follow',
      referrer = 'client'
    } = options;
    
    // 创建AbortController用于超时控制
    const controller = new AbortController();
    const signal = controller.signal;
    
    // 设置超时
    const timeoutId = setTimeout(() => {
      controller.abort();
    }, timeout);
    
    try {
      const response = await fetch(url, {
        method,
        headers,
        body,
        credentials,
        mode,
        cache,
        redirect,
        referrer,
        signal
      });
      
      clearTimeout(timeoutId);
      
      // 检查响应状态
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      
      // 根据Content-Type解析响应
      const contentType = response.headers.get('content-type');
      let data;
      
      if (contentType && contentType.includes('application/json')) {
        data = await response.json();
      } else if (contentType && contentType.includes('text/')) {
        data = await response.text();
      } else if (contentType && contentType.includes('multipart/form-data')) {
        data = await response.formData();
      } else {
        data = await response.blob();
      }
      
      return {
        data,
        status: response.status,
        statusText: response.statusText,
        headers: response.headers,
        response
      };
    } catch (error) {
      clearTimeout(timeoutId);
      
      if (error.name === 'AbortError') {
        throw new Error('Request timeout');
      }
      
      throw error;
    }
  }
  
  // 性能对比
  static async performanceComparison() {
    const testUrl = 'https://jsonplaceholder.typicode.com/posts/1';
    const iterations = 10;
    const results = {
      xhr: { times: [], avg: 0 },
      fetch: { times: [], avg: 0 }
    };
    
    console.log('Starting performance comparison...');
    
    // 测试XHR
    for (let i = 0; i < iterations; i++) {
      const start = performance.now();
      await this.xhrRequest(testUrl);
      const end = performance.now();
      results.xhr.times.push(end - start);
    }
    
    // 测试Fetch
    for (let i = 0; i < iterations; i++) {
      const start = performance.now();
      await this.fetchRequest(testUrl);
      const end = performance.now();
      results.fetch.times.push(end - start);
    }
    
    // 计算平均值
    results.xhr.avg = results.xhr.times.reduce((a, b) => a + b, 0) / iterations;
    results.fetch.avg = results.fetch.times.reduce((a, b) => a + b, 0) / iterations;
    
    console.log('Performance results:', results);
    console.log(`XHR average: ${results.xhr.avg.toFixed(2)}ms`);
    console.log(`Fetch average: ${results.fetch.avg.toFixed(2)}ms`);
    
    return results;
  }
}
1.2 Fetch API的局限性及解决方案
javascript 复制代码
class FetchLimitations {
  // 处理Fetch不支持的特性
  static getFetchPolyfills() {
    const polyfills = {};
    
    // 1. 进度监控
    if (!('upload' in new Request(''))) {
      polyfills.progress = async function(url, options = {}) {
        const { onProgress, ...fetchOptions } = options;
        
        // 使用XHR来获取进度
        return new Promise((resolve, reject) => {
          const xhr = new XMLHttpRequest();
          
          xhr.open(options.method || 'GET', url);
          
          // 设置请求头
          if (options.headers) {
            Object.entries(options.headers).forEach(([key, value]) => {
              xhr.setRequestHeader(key, value);
            });
          }
          
          // 进度事件
          if (onProgress) {
            xhr.upload.onprogress = onProgress;
            xhr.onprogress = onProgress;
          }
          
          xhr.onload = function() {
            if (xhr.status >= 200 && xhr.status < 300) {
              let data;
              
              try {
                data = JSON.parse(xhr.responseText);
              } catch {
                data = xhr.responseText;
              }
              
              resolve({
                data,
                status: xhr.status,
                statusText: xhr.statusText
              });
            } else {
              reject(new Error(`HTTP ${xhr.status}`));
            }
          };
          
          xhr.onerror = reject;
          xhr.ontimeout = reject;
          
          xhr.send(options.body);
        });
      };
    }
    
    // 2. 超时处理
    if (!('timeout' in new Request(''))) {
      polyfills.timeout = function(url, options = {}) {
        const { timeout = 30000, ...fetchOptions } = options;
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), timeout);
        
        return fetch(url, { ...fetchOptions, signal: controller.signal })
          .finally(() => clearTimeout(timeoutId));
      };
    }
    
    // 3. 请求取消
    polyfills.cancelable = function(url, options = {}) {
      const controller = new AbortController();
      const promise = fetch(url, { ...options, signal: controller.signal });
      
      return {
        promise,
        cancel: () => controller.abort()
      };
    };
    
    return polyfills;
  }
  
  // 处理流式响应
  static async handleStreamResponse(url, onChunk, onComplete) {
    try {
      const response = await fetch(url);
      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let result = '';
      
      while (true) {
        const { done, value } = await reader.read();
        
        if (done) {
          if (onComplete) onComplete(result);
          break;
        }
        
        // 处理chunk
        const chunk = decoder.decode(value, { stream: true });
        result += chunk;
        
        if (onChunk) onChunk(chunk, result);
      }
      
      return result;
    } catch (error) {
      throw error;
    }
  }
  
  // 处理大文件上传
  static async uploadLargeFile(url, file, options = {}) {
    const {
      chunkSize = 1024 * 1024, // 1MB chunks
      onProgress,
      onComplete,
      onError
    } = options;
    
    // 创建FormData
    const formData = new FormData();
    formData.append('file', file);
    formData.append('fileName', file.name);
    formData.append('fileSize', file.size);
    formData.append('chunkSize', chunkSize);
    formData.append('totalChunks', Math.ceil(file.size / chunkSize));
    
    // 如果文件很大,使用分片上传
    if (file.size > chunkSize) {
      return this.uploadInChunks(url, file, {
        chunkSize,
        onProgress,
        onComplete,
        onError
      });
    }
    
    // 普通上传
    return fetch(url, {
      method: 'POST',
      body: formData
    });
  }
  
  static async uploadInChunks(url, file, options) {
    const {
      chunkSize = 1024 * 1024,
      onProgress,
      onComplete,
      onError
    } = options;
    
    const totalChunks = Math.ceil(file.size / chunkSize);
    const fileId = `${Date.now()}-${Math.random().toString(36).substr(2)}`;
    let uploadedChunks = 0;
    
    // 上传每个分片
    for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
      const start = chunkIndex * chunkSize;
      const end = Math.min(start + chunkSize, file.size);
      const chunk = file.slice(start, end);
      
      const formData = new FormData();
      formData.append('fileId', fileId);
      formData.append('chunk', chunk);
      formData.append('chunkIndex', chunkIndex);
      formData.append('totalChunks', totalChunks);
      formData.append('fileName', file.name);
      formData.append('fileSize', file.size);
      
      try {
        const response = await fetch(`${url}/chunk`, {
          method: 'POST',
          body: formData
        });
        
        if (!response.ok) {
          throw new Error(`Chunk ${chunkIndex} upload failed`);
        }
        
        uploadedChunks++;
        
        // 报告进度
        if (onProgress) {
          const progress = (uploadedChunks / totalChunks) * 100;
          onProgress(progress, chunkIndex, totalChunks);
        }
      } catch (error) {
        if (onError) onError(error, chunkIndex);
        throw error;
      }
    }
    
    // 所有分片上传完成,合并文件
    try {
      const response = await fetch(`${url}/merge`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          fileId,
          fileName: file.name,
          totalChunks
        })
      });
      
      if (onComplete) onComplete(response);
      return response;
    } catch (error) {
      if (onError) onError(error);
      throw error;
    }
  }
}

二、增强型Fetch封装

2.1 完整的HTTP客户端实现
javascript 复制代码
class HttpClient {
  constructor(baseURL = '', defaultOptions = {}) {
    this.baseURL = baseURL;
    this.defaultOptions = {
      headers: {
        'Content-Type': 'application/json',
        ...defaultOptions.headers
      },
      timeout: 30000,
      credentials: 'include',
      mode: 'cors',
      ...defaultOptions
    };
    
    this.interceptors = {
      request: [],
      response: [],
      error: []
    };
    
    this.pendingRequests = new Map();
    this.cache = new Map();
    this.retryConfig = {
      maxRetries: 3,
      retryDelay: 1000,
      retryOn: [408, 429, 500, 502, 503, 504]
    };
    
    // 初始化请求队列
    this.requestQueue = [];
    this.maxConcurrent = 6;
    this.activeRequests = 0;
    
    this.init();
  }
  
  init() {
    // 添加默认拦截器
    this.addDefaultInterceptors();
  }
  
  addDefaultInterceptors() {
    // 请求拦截器:添加认证token
    this.interceptors.request.use(
      async (config) => {
        // 从localStorage或cookie获取token
        const token = localStorage.getItem('auth_token') || 
                      this.getCookie('auth_token');
        
        if (token) {
          config.headers = {
            ...config.headers,
            'Authorization': `Bearer ${token}`
          };
        }
        
        // 添加请求时间戳防止缓存
        if (config.method?.toLowerCase() === 'get') {
          const url = new URL(config.url, window.location.origin);
          url.searchParams.set('_t', Date.now());
          config.url = url.toString();
        }
        
        return config;
      }
    );
    
    // 响应拦截器:处理通用错误
    this.interceptors.response.use(
      (response) => response,
      async (error) => {
        // 处理认证失败
        if (error.status === 401) {
          // 刷新token或跳转到登录页
          await this.handleUnauthorized();
        }
        
        // 处理服务器错误
        if (error.status >= 500) {
          console.error('Server error:', error);
        }
        
        return Promise.reject(error);
      }
    );
  }
  
  // 核心请求方法
  async request(url, options = {}) {
    const requestId = this.generateRequestId(url, options);
    
    // 检查是否已有相同的请求在处理中
    if (this.pendingRequests.has(requestId)) {
      return this.pendingRequests.get(requestId);
    }
    
    // 合并配置
    const config = {
      url: this.baseURL ? `${this.baseURL}${url}` : url,
      ...this.defaultOptions,
      ...options
    };
    
    // 执行请求拦截器
    let processedConfig = config;
    for (const interceptor of this.interceptors.request) {
      processedConfig = await interceptor(processedConfig);
    }
    
    // 创建请求Promise
    const requestPromise = this.executeRequest(processedConfig, requestId);
    
    // 存储pending请求
    this.pendingRequests.set(requestId, requestPromise);
    
    try {
      const response = await requestPromise;
      
      // 执行响应拦截器
      let processedResponse = response;
      for (const interceptor of this.interceptors.response) {
        processedResponse = await interceptor(processedResponse);
      }
      
      return processedResponse;
    } catch (error) {
      // 执行错误拦截器
      for (const interceptor of this.interceptors.error) {
        await interceptor(error, processedConfig);
      }
      
      throw error;
    } finally {
      // 清理pending请求
      this.pendingRequests.delete(requestId);
    }
  }
  
  async executeRequest(config, requestId) {
    const {
      url,
      method = 'GET',
      headers,
      body,
      timeout,
      signal,
      cache: cacheOption,
      ...restOptions
    } = config;
    
    // 检查缓存
    if (method.toUpperCase() === 'GET' && cacheOption) {
      const cached = this.getFromCache(url, cacheOption);
      if (cached) {
        return cached;
      }
    }
    
    // 创建AbortController用于超时控制
    const controller = new AbortController();
    const abortSignal = signal || controller.signal;
    
    // 设置超时
    const timeoutId = timeout ? setTimeout(() => {
      controller.abort();
    }, timeout) : null;
    
    try {
      const fetchOptions = {
        method,
        headers,
        signal: abortSignal,
        ...restOptions
      };
      
      // 处理请求体
      if (body) {
        if (body instanceof FormData || body instanceof URLSearchParams) {
          fetchOptions.body = body;
          // FormData会自己设置Content-Type
          if (fetchOptions.headers && fetchOptions.headers['Content-Type']) {
            delete fetchOptions.headers['Content-Type'];
          }
        } else if (typeof body === 'object') {
          fetchOptions.body = JSON.stringify(body);
        } else {
          fetchOptions.body = body;
        }
      }
      
      const response = await fetch(url, fetchOptions);
      
      // 清除超时定时器
      if (timeoutId) clearTimeout(timeoutId);
      
      // 解析响应
      const contentType = response.headers.get('content-type');
      let data;
      
      if (contentType && contentType.includes('application/json')) {
        data = await response.json();
      } else if (contentType && contentType.includes('text/')) {
        data = await response.text();
      } else if (contentType && contentType.includes('multipart/form-data')) {
        data = await response.formData();
      } else {
        data = await response.blob();
      }
      
      const result = {
        data,
        status: response.status,
        statusText: response.statusText,
        headers: response.headers,
        config,
        requestId
      };
      
      // 缓存响应
      if (method.toUpperCase() === 'GET' && cacheOption && response.ok) {
        this.setCache(url, result, cacheOption);
      }
      
      if (!response.ok) {
        throw this.createError(response, data, config);
      }
      
      return result;
    } catch (error) {
      // 清除超时定时器
      if (timeoutId) clearTimeout(timeoutId);
      
      if (error.name === 'AbortError') {
        throw this.createError(null, 'Request timeout', config);
      }
      
      throw error;
    }
  }
  
  // 创建错误对象
  createError(response, data, config) {
    const error = new Error(
      response ? `HTTP ${response.status}: ${response.statusText}` : 'Network Error'
    );
    
    Object.assign(error, {
      config,
      response: response ? {
        data,
        status: response.status,
        statusText: response.statusText,
        headers: response.headers
      } : null,
      isHttpError: true
    });
    
    return error;
  }
  
  // 生成请求ID
  generateRequestId(url, options) {
    const { method = 'GET', body } = options;
    const timestamp = Date.now();
    const bodyHash = body ? this.hashString(JSON.stringify(body)) : '';
    
    return `${method}_${url}_${bodyHash}_${timestamp}`;
  }
  
  // 简单的字符串哈希
  hashString(str) {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash;
    }
    return hash.toString(36);
  }
  
  // HTTP方法快捷方式
  get(url, options = {}) {
    return this.request(url, { ...options, method: 'GET' });
  }
  
  post(url, data, options = {}) {
    return this.request(url, { ...options, method: 'POST', body: data });
  }
  
  put(url, data, options = {}) {
    return this.request(url, { ...options, method: 'PUT', body: data });
  }
  
  patch(url, data, options = {}) {
    return this.request(url, { ...options, method: 'PATCH', body: data });
  }
  
  delete(url, options = {}) {
    return this.request(url, { ...options, method: 'DELETE' });
  }
  
  head(url, options = {}) {
    return this.request(url, { ...options, method: 'HEAD' });
  }
  
  options(url, options = {}) {
    return this.request(url, { ...options, method: 'OPTIONS' });
  }
  
  // 拦截器管理
  interceptors = {
    request: {
      handlers: [],
      use(handler) {
        this.handlers.push(handler);
        return () => {
          const index = this.handlers.indexOf(handler);
          if (index > -1) this.handlers.splice(index, 1);
        };
      },
      eject(handler) {
        const index = this.handlers.indexOf(handler);
        if (index > -1) this.handlers.splice(index, 1);
      }
    },
    response: {
      handlers: [],
      use(onFulfilled, onRejected) {
        this.handlers.push({ onFulfilled, onRejected });
        return () => {
          const index = this.handlers.findIndex(h => 
            h.onFulfilled === onFulfilled && h.onRejected === onRejected
          );
          if (index > -1) this.handlers.splice(index, 1);
        };
      },
      eject(handler) {
        const index = this.handlers.findIndex(h => 
          h.onFulfilled === handler.onFulfilled && 
          h.onRejected === handler.onRejected
        );
        if (index > -1) this.handlers.splice(index, 1);
      }
    },
    error: {
      handlers: [],
      use(handler) {
        this.handlers.push(handler);
        return () => {
          const index = this.handlers.indexOf(handler);
          if (index > -1) this.handlers.splice(index, 1);
        };
      },
      eject(handler) {
        const index = this.handlers.indexOf(handler);
        if (index > -1) this.handlers.splice(index, 1);
      }
    }
  };
  
  // 缓存管理
  getFromCache(url, cacheOption) {
    if (!this.cache.has(url)) return null;
    
    const cached = this.cache.get(url);
    const now = Date.now();
    
    // 检查是否过期
    if (cacheOption === 'no-cache' || 
        (cached.expiry && cached.expiry < now)) {
      this.cache.delete(url);
      return null;
    }
    
    return cached.data;
  }
  
  setCache(url, data, cacheOption) {
    let expiry = null;
    
    if (typeof cacheOption === 'number') {
      expiry = Date.now() + cacheOption; // 毫秒
    } else if (cacheOption === 'short') {
      expiry = Date.now() + (5 * 60 * 1000); // 5分钟
    } else if (cacheOption === 'long') {
      expiry = Date.now() + (60 * 60 * 1000); // 1小时
    }
    
    this.cache.set(url, { data, expiry });
    
    // 清理过期缓存
    this.cleanupCache();
  }
  
  cleanupCache() {
    const now = Date.now();
    for (const [url, cached] of this.cache.entries()) {
      if (cached.expiry && cached.expiry < now) {
        this.cache.delete(url);
      }
    }
  }
  
  // 清除缓存
  clearCache(url = null) {
    if (url) {
      this.cache.delete(url);
    } else {
      this.cache.clear();
    }
  }
  
  // 从cookie获取值
  getCookie(name) {
    const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
    return match ? decodeURIComponent(match[2]) : null;
  }
  
  // 处理未授权
  async handleUnauthorized() {
    // 尝试刷新token
    try {
      const refreshToken = localStorage.getItem('refresh_token');
      if (refreshToken) {
        const response = await this.post('/auth/refresh', {
          refresh_token: refreshToken
        });
        
        if (response.data.access_token) {
          localStorage.setItem('auth_token', response.data.access_token);
          return true;
        }
      }
    } catch (error) {
      // 刷新失败,清除本地认证信息
      localStorage.removeItem('auth_token');
      localStorage.removeItem('refresh_token');
      
      // 跳转到登录页
      window.location.href = '/login';
    }
    
    return false;
  }
  
  // 批量请求
  async all(requests) {
    return Promise.all(requests);
  }
  
  // 请求并发控制
  async spread(requests, maxConcurrent = this.maxConcurrent) {
    const results = [];
    let index = 0;
    
    const runNext = async () => {
      if (index >= requests.length) return;
      
      const currentIndex = index++;
      const request = requests[currentIndex];
      
      try {
        const result = await request();
        results[currentIndex] = { status: 'fulfilled', value: result };
      } catch (error) {
        results[currentIndex] = { status: 'rejected', reason: error };
      }
      
      // 递归执行下一个
      await runNext();
    };
    
    // 创建并发执行器
    const concurrentPromises = [];
    for (let i = 0; i < Math.min(maxConcurrent, requests.length); i++) {
      concurrentPromises.push(runNext());
    }
    
    await Promise.all(concurrentPromises);
    return results;
  }
}
2.2 请求拦截器的高级实现
javascript 复制代码
class AdvancedInterceptor {
  constructor(httpClient) {
    this.httpClient = httpClient;
    this.setupAdvancedInterceptors();
  }
  
  setupAdvancedInterceptors() {
    // 1. 请求节流/防抖拦截器
    this.addThrottleInterceptor();
    
    // 2. 请求合并拦截器
    this.addBatchInterceptor();
    
    // 3. 请求重试拦截器
    this.addRetryInterceptor();
    
    // 4. 请求缓存拦截器
    this.addCacheInterceptor();
    
    // 5. 请求日志拦截器
    this.addLoggingInterceptor();
    
    // 6. 性能监控拦截器
    this.addPerformanceInterceptor();
  }
  
  addThrottleInterceptor() {
    const requestTimestamps = new Map();
    const requestQueue = new Map();
    
    this.httpClient.interceptors.request.use(
      async (config) => {
        const { throttle = false, debounce = false, delay = 1000 } = config;
        
        if (!throttle && !debounce) return config;
        
        const requestKey = `${config.method}_${config.url}`;
        
        // 节流处理
        if (throttle) {
          const lastRequestTime = requestTimestamps.get(requestKey) || 0;
          const now = Date.now();
          
          if (now - lastRequestTime < delay) {
            // 仍在节流期内,延迟请求
            await new Promise(resolve => {
              setTimeout(resolve, delay - (now - lastRequestTime));
            });
          }
          
          requestTimestamps.set(requestKey, Date.now());
        }
        
        // 防抖处理
        if (debounce) {
          return new Promise((resolve) => {
            // 清除之前的定时器
            if (requestQueue.has(requestKey)) {
              clearTimeout(requestQueue.get(requestKey));
            }
            
            // 设置新的定时器
            const timerId = setTimeout(() => {
              requestQueue.delete(requestKey);
              resolve(config);
            }, delay);
            
            requestQueue.set(requestKey, timerId);
          });
        }
        
        return config;
      }
    );
  }
  
  addBatchInterceptor() {
    const batchRequests = new Map();
    const BATCH_DELAY = 100; // 100ms批处理窗口
    
    this.httpClient.interceptors.request.use(
      (config) => {
        const { batch = false, batchKey } = config;
        
        if (!batch) return config;
        
        const key = batchKey || config.url.split('?')[0];
        
        return new Promise((resolve) => {
          if (!batchRequests.has(key)) {
            batchRequests.set(key, {
              timer: null,
              requests: []
            });
          }
          
          const batchInfo = batchRequests.get(key);
          batchInfo.requests.push({ config, resolve });
          
          // 清除之前的定时器
          if (batchInfo.timer) {
            clearTimeout(batchInfo.timer);
          }
          
          // 设置新的定时器
          batchInfo.timer = setTimeout(async () => {
            const requests = batchInfo.requests;
            batchRequests.delete(key);
            
            // 合并请求
            const mergedConfig = this.mergeBatchRequests(requests);
            const response = await this.httpClient.request(mergedConfig.url, mergedConfig);
            
            // 分发响应
            this.distributeBatchResponse(requests, response);
          }, BATCH_DELAY);
        });
      }
    );
  }
  
  mergeBatchRequests(requests) {
    // 简单示例:合并GET请求参数
    const firstConfig = requests[0].config;
    const url = new URL(firstConfig.url, window.location.origin);
    
    // 收集所有请求的参数
    const allParams = [];
    requests.forEach(({ config }) => {
      const requestUrl = new URL(config.url, window.location.origin);
      const params = Object.fromEntries(requestUrl.searchParams.entries());
      allParams.push(params);
    });
    
    // 设置批处理参数
    url.searchParams.set('batch', JSON.stringify(allParams));
    
    return {
      ...firstConfig,
      url: url.toString(),
      batch: false // 防止递归
    };
  }
  
  distributeBatchResponse(requests, batchResponse) {
    // 这里需要根据实际API的批处理响应格式来分发
    // 假设API返回数组,顺序对应请求顺序
    if (Array.isArray(batchResponse.data)) {
      requests.forEach(({ resolve }, index) => {
        const individualResponse = {
          ...batchResponse,
          data: batchResponse.data[index]
        };
        resolve(individualResponse);
      });
    }
  }
  
  addRetryInterceptor() {
    this.httpClient.interceptors.response.use(
      (response) => response,
      async (error) => {
        const config = error.config || {};
        const { retry = this.httpClient.retryConfig, __retryCount = 0 } = config;
        
        // 检查是否应该重试
        if (!this.shouldRetry(error, retry, __retryCount)) {
          return Promise.reject(error);
        }
        
        // 增加重试计数
        config.__retryCount = __retryCount + 1;
        
        // 计算延迟时间(指数退避)
        const delay = retry.retryDelay * Math.pow(2, __retryCount);
        
        // 等待延迟时间
        await new Promise(resolve => setTimeout(resolve, delay));
        
        // 重试请求
        return this.httpClient.request(config.url, config);
      }
    );
  }
  
  shouldRetry(error, retryConfig, retryCount) {
    // 检查最大重试次数
    if (retryCount >= retryConfig.maxRetries) return false;
    
    // 检查错误类型
    if (!error.response) {
      // 网络错误应该重试
      return true;
    }
    
    // 检查状态码
    const status = error.response.status;
    return retryConfig.retryOn.includes(status);
  }
  
  addCacheInterceptor() {
    this.httpClient.interceptors.request.use(
      (config) => {
        const { cache = false, forceRefresh = false } = config;
        
        if (!cache || forceRefresh) return config;
        
        // 检查内存缓存
        const cached = this.httpClient.getFromCache(config.url, cache);
        if (cached) {
          // 返回缓存的响应,不再发送请求
          return Promise.reject({
            config,
            response: cached,
            isCacheHit: true
          });
        }
        
        return config;
      }
    );
    
    // 处理缓存命中
    this.httpClient.interceptors.response.use(
      (response) => response,
      (error) => {
        if (error.isCacheHit) {
          return Promise.resolve(error.response);
        }
        return Promise.reject(error);
      }
    );
  }
  
  addLoggingInterceptor() {
    // 请求日志
    this.httpClient.interceptors.request.use(
      (config) => {
        console.group(`🌐 Request: ${config.method} ${config.url}`);
        console.log('Config:', config);
        console.groupEnd();
        
        // 添加请求时间戳
        config.__startTime = performance.now();
        
        return config;
      }
    );
    
    // 响应日志
    this.httpClient.interceptors.response.use(
      (response) => {
        const duration = performance.now() - response.config.__startTime;
        
        console.group(`✅ Response: ${response.status} ${response.config.url}`);
        console.log('Response:', response);
        console.log(`Duration: ${duration.toFixed(2)}ms`);
        console.groupEnd();
        
        // 发送性能数据到监控系统
        this.sendMetrics({
          url: response.config.url,
          method: response.config.method,
          status: response.status,
          duration,
          timestamp: Date.now()
        });
        
        return response;
      },
      (error) => {
        const duration = error.config ? 
          performance.now() - error.config.__startTime : 0;
        
        console.group(`❌ Error: ${error.config?.url}`);
        console.log('Error:', error);
        console.log(`Duration: ${duration.toFixed(2)}ms`);
        console.groupEnd();
        
        // 发送错误数据到监控系统
        this.sendErrorMetrics({
          url: error.config?.url,
          method: error.config?.method,
          status: error.response?.status,
          duration,
          error: error.message,
          timestamp: Date.now()
        });
        
        return Promise.reject(error);
      }
    );
  }
  
  addPerformanceInterceptor() {
    const performanceData = [];
    const MAX_PERFORMANCE_ENTRIES = 100;
    
    this.httpClient.interceptors.request.use(
      (config) => {
        // 使用Performance API标记请求开始
        if (window.performance && window.performance.mark) {
          const markName = `request_start_${config.url.replace(/[^a-z0-9]/gi, '_')}`;
          window.performance.mark(markName);
          config.__performanceMark = markName;
        }
        
        return config;
      }
    );
    
    this.httpClient.interceptors.response.use(
      (response) => {
        // 测量请求性能
        if (window.performance && response.config.__performanceMark) {
          const markName = response.config.__performanceMark;
          const measureName = `request_${response.config.url.replace(/[^a-z0-9]/gi, '_')}`;
          
          window.performance.mark(`${markName}_end`);
          window.performance.measure(
            measureName,
            markName,
            `${markName}_end`
          );
          
          // 获取测量结果
          const measures = window.performance.getEntriesByName(measureName);
          if (measures.length > 0) {
            const measure = measures[0];
            
            performanceData.push({
              url: response.config.url,
              duration: measure.duration,
              startTime: measure.startTime,
              timestamp: Date.now()
            });
            
            // 限制数据大小
            if (performanceData.length > MAX_PERFORMANCE_ENTRIES) {
              performanceData.shift();
            }
          }
        }
        
        return response;
      }
    );
  }
  
  sendMetrics(metric) {
    // 发送到监控系统(例如:Google Analytics,自建监控等)
    if (window.gtag) {
      window.gtag('event', 'request_completed', metric);
    }
    
    // 或者发送到后端
    if (navigator.sendBeacon) {
      const data = new Blob([JSON.stringify(metric)], { type: 'application/json' });
      navigator.sendBeacon('/api/metrics', data);
    }
  }
  
  sendErrorMetrics(errorMetric) {
    // 发送错误监控
    if (window.Rollbar) {
      window.Rollbar.error('HTTP Request Error', errorMetric);
    }
    
    // 发送到后端
    if (navigator.sendBeacon) {
      const data = new Blob([JSON.stringify(errorMetric)], { type: 'application/json' });
      navigator.sendBeacon('/api/errors', data);
    }
  }
  
  // 获取性能报告
  getPerformanceReport() {
    const totalRequests = performanceData.length;
    
    if (totalRequests === 0) {
      return { averageDuration: 0, totalRequests: 0 };
    }
    
    const totalDuration = performanceData.reduce((sum, entry) => sum + entry.duration, 0);
    const averageDuration = totalDuration / totalRequests;
    
    // 按URL分组
    const urlStats = {};
    performanceData.forEach(entry => {
      if (!urlStats[entry.url]) {
        urlStats[entry.url] = {
          count: 0,
          totalDuration: 0,
          durations: []
        };
      }
      
      urlStats[entry.url].count++;
      urlStats[entry.url].totalDuration += entry.duration;
      urlStats[entry.url].durations.push(entry.duration);
    });
    
    // 计算每个URL的平均值
    Object.keys(urlStats).forEach(url => {
      const stats = urlStats[url];
      stats.averageDuration = stats.totalDuration / stats.count;
      
      // 计算p95
      stats.durations.sort((a, b) => a - b);
      const p95Index = Math.floor(stats.durations.length * 0.95);
      stats.p95 = stats.durations[p95Index];
    });
    
    return {
      totalRequests,
      averageDuration,
      urlStats,
      recentRequests: performanceData.slice(-10)
    };
  }
}

三、请求取消与并发控制

3.1 高级请求取消机制
javascript 复制代码
class RequestCancellation {
  constructor() {
    this.cancelTokens = new Map();
    this.cancelSources = new Map();
    this.requestGroups = new Map();
  }
  
  // 创建取消令牌
  createCancelToken() {
    const source = {
      token: null,
      cancel: null
    };
    
    const token = new Promise((resolve, reject) => {
      source.cancel = (reason) => {
        reject(new RequestCancellationError(reason || 'Request cancelled'));
      };
    });
    
    source.token = token;
    const tokenId = this.generateTokenId();
    this.cancelSources.set(tokenId, source);
    
    return {
      token,
      cancel: source.cancel,
      tokenId
    };
  }
  
  // 为请求添加取消支持
  withCancellation(requestPromise, cancelToken, requestId) {
    if (!cancelToken) return requestPromise;
    
    const abortController = new AbortController();
    const signal = abortController.signal;
    
    // 包装请求以支持取消
    const wrappedPromise = Promise.race([
      requestPromise,
      cancelToken.then(
        () => Promise.reject(new RequestCancellationError('Request cancelled by token'))),
      new Promise((_, reject) => {
        signal.addEventListener('abort', () => {
          reject(new RequestCancellationError('Request aborted'));
        });
      })
    ]);
    
    // 存储取消控制器
    this.cancelTokens.set(requestId, abortController);
    
    // 清理函数
    wrappedPromise.finally(() => {
      this.cancelTokens.delete(requestId);
    });
    
    return wrappedPromise;
  }
  
  // 取消特定请求
  cancelRequest(requestId, reason) {
    const controller = this.cancelTokens.get(requestId);
    if (controller) {
      controller.abort(reason);
      this.cancelTokens.delete(requestId);
      return true;
    }
    return false;
  }
  
  // 取消一组请求
  cancelGroup(groupId, reason) {
    const group = this.requestGroups.get(groupId);
    if (!group) return false;
    
    group.forEach(requestId => {
      this.cancelRequest(requestId, reason);
    });
    
    this.requestGroups.delete(groupId);
    return true;
  }
  
  // 取消所有请求
  cancelAll(reason) {
    Array.from(this.cancelTokens.keys()).forEach(requestId => {
      this.cancelRequest(requestId, reason);
    });
    
    Array.from(this.requestGroups.keys()).forEach(groupId => {
      this.cancelGroup(groupId, reason);
    });
    
    return true;
  }
  
  // 将请求添加到组
  addToGroup(requestId, groupId) {
    if (!this.requestGroups.has(groupId)) {
      this.requestGroups.set(groupId, new Set());
    }
    
    this.requestGroups.get(groupId).add(requestId);
    
    // 返回移除函数
    return () => {
      const group = this.requestGroups.get(groupId);
      if (group) {
        group.delete(requestId);
        if (group.size === 0) {
          this.requestGroups.delete(groupId);
        }
      }
    };
  }
  
  // 生成令牌ID
  generateTokenId() {
    return `token_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  
  // 创建竞速请求(第一个成功或全部失败)
  createRace(requests, options = {}) {
    const {
      cancelPrevious = true,
      groupId = `race_${Date.now()}`
    } = options;
    
    // 如果取消之前的请求
    if (cancelPrevious) {
      this.cancelGroup(groupId, 'Superseded by new request');
    }
    
    const racePromise = Promise.race(requests);
    
    // 为每个请求添加到组
    requests.forEach((request, index) => {
      const requestId = `${groupId}_${index}`;
      this.addToGroup(requestId, groupId);
      
      // 请求完成后从组中移除
      request.then(
        () => this.removeFromGroup(requestId, groupId),
        () => this.removeFromGroup(requestId, groupId)
      );
    });
    
    return racePromise;
  }
  
  // 从组中移除请求
  removeFromGroup(requestId, groupId) {
    const group = this.requestGroups.get(groupId);
    if (group) {
      group.delete(requestId);
      if (group.size === 0) {
        this.requestGroups.delete(groupId);
      }
    }
  }
  
  // 创建请求池
  createRequestPool(maxConcurrent = 5) {
    const queue = [];
    let activeCount = 0;
    
    const runNext = async () => {
      if (activeCount >= maxConcurrent || queue.length === 0) {
        return;
      }
      
      activeCount++;
      const { request, resolve, reject } = queue.shift();
      
      try {
        const result = await request();
        resolve(result);
      } catch (error) {
        reject(error);
      } finally {
        activeCount--;
        runNext();
      }
    };
    
    const enqueue = (request) => {
      return new Promise((resolve, reject) => {
        queue.push({ request, resolve, reject });
        runNext();
      });
    };
    
    return {
      enqueue,
      getQueueSize: () => queue.length,
      getActiveCount: () => activeCount
    };
  }
  
  // 批量请求的并发控制
  async batchWithConcurrency(requests, concurrency = 3) {
    const results = new Array(requests.length);
    let currentIndex = 0;
    
    const executeNext = async () => {
      if (currentIndex >= requests.length) return;
      
      const index = currentIndex++;
      const request = requests[index];
      
      try {
        results[index] = await request();
      } catch (error) {
        results[index] = error;
      }
      
      // 执行下一个
      await executeNext();
    };
    
    // 创建并发的执行器
    const concurrentPromises = [];
    for (let i = 0; i < Math.min(concurrency, requests.length); i++) {
      concurrentPromises.push(executeNext());
    }
    
    await Promise.all(concurrentPromises);
    return results;
  }
}

// 自定义取消错误
class RequestCancellationError extends Error {
  constructor(message = 'Request cancelled') {
    super(message);
    this.name = 'RequestCancellationError';
    this.isCancelled = true;
  }
}

// 使用示例
class CancellationExample {
  static async demonstrate() {
    const cancellation = new RequestCancellation();
    
    // 创建取消令牌
    const { token: cancelToken, cancel } = cancellation.createCancelToken();
    
    // 创建请求
    const request1 = fetch('https://api.example.com/data1');
    const request2 = fetch('https://api.example.com/data2');
    
    // 包装请求以支持取消
    const cancellableRequest1 = cancellation.withCancellation(
      request1,
      cancelToken,
      'request_1'
    );
    
    const cancellableRequest2 = cancellation.withCancellation(
      request2,
      cancelToken,
      'request_2'
    );
    
    // 将请求添加到组
    cancellation.addToGroup('request_1', 'data_fetch_group');
    cancellation.addToGroup('request_2', 'data_fetch_group');
    
    // 模拟3秒后取消所有请求
    setTimeout(() => {
      cancellation.cancelGroup('data_fetch_group', 'User cancelled');
    }, 3000);
    
    try {
      const results = await Promise.all([
        cancellableRequest1,
        cancellableRequest2
      ]);
      
      console.log('Requests completed:', results);
    } catch (error) {
      if (error.isCancelled) {
        console.log('Requests were cancelled:', error.message);
      } else {
        console.error('Request failed:', error);
      }
    }
    
    // 使用请求池
    const pool = cancellation.createRequestPool(2);
    
    const requests = [
      () => fetch('https://api.example.com/item/1'),
      () => fetch('https://api.example.com/item/2'),
      () => fetch('https://api.example.com/item/3'),
      () => fetch('https://api.example.com/item/4'),
      () => fetch('https://api.example.com/item/5')
    ];
    
    const poolResults = await Promise.all(
      requests.map(request => pool.enqueue(request))
    );
    
    console.log('Pool results:', poolResults);
  }
}
3.2 智能请求调度器
javascript 复制代码
class IntelligentRequestScheduler {
  constructor(options = {}) {
    this.options = {
      maxConcurrent: 6,
      priorityLevels: ['high', 'normal', 'low'],
      retryEnabled: true,
      cacheEnabled: true,
      offlineQueueEnabled: true,
      ...options
    };
    
    this.queues = {
      high: [],
      normal: [],
      low: []
    };
    
    this.activeRequests = new Set();
    this.requestCache = new Map();
    this.offlineQueue = [];
    this.isOnline = navigator.onLine;
    this.retryStrategies = new Map();
    this.requestStats = new Map();
    
    this.init();
  }
  
  init() {
    // 监听网络状态
    window.addEventListener('online', () => {
      this.isOnline = true;
      this.processOfflineQueue();
    });
    
    window.addEventListener('offline', () => {
      this.isOnline = false;
    });
    
    // 启动调度器
    this.startScheduler();
    
    // 初始化重试策略
    this.initRetryStrategies();
  }
  
  startScheduler() {
    setInterval(() => {
      this.processQueues();
    }, 100); // 每100ms处理一次队列
  }
  
  initRetryStrategies() {
    // 默认重试策略
    this.retryStrategies.set('default', {
      maxRetries: 3,
      baseDelay: 1000,
      maxDelay: 10000,
      backoffMultiplier: 2,
      retryableStatuses: [408, 429, 500, 502, 503, 504],
      retryableErrors: ['ECONNABORTED', 'ETIMEDOUT', 'NETWORK_ERROR']
    });
    
    // 关键请求的重试策略
    this.retryStrategies.set('critical', {
      maxRetries: 5,
      baseDelay: 500,
      maxDelay: 30000,
      backoffMultiplier: 1.5,
      retryableStatuses: [408, 429, 500, 502, 503, 504, 502],
      retryableErrors: ['ECONNABORTED', 'ETIMEDOUT', 'NETWORK_ERROR']
    });
    
    // 非关键请求的重试策略
    this.retryStrategies.set('non-critical', {
      maxRetries: 1,
      baseDelay: 2000,
      maxDelay: 5000,
      backoffMultiplier: 2,
      retryableStatuses: [500, 502, 503, 504],
      retryableErrors: ['NETWORK_ERROR']
    });
  }
  
  // 调度请求
  schedule(request, options = {}) {
    const {
      priority = 'normal',
      retryStrategy = 'default',
      cacheKey = null,
      offlineFallback = false,
      timeout = 30000,
      group = null
    } = options;
    
    const requestId = this.generateRequestId(request, options);
    const requestInfo = {
      id: requestId,
      request,
      options,
      priority,
      retryStrategy,
      cacheKey,
      offlineFallback,
      timeout,
      group,
      status: 'pending',
      retryCount: 0,
      createdAt: Date.now(),
      scheduledAt: null,
      completedAt: null
    };
    
    // 检查缓存
    if (this.options.cacheEnabled && cacheKey) {
      const cached = this.requestCache.get(cacheKey);
      if (cached && !this.isCacheExpired(cached)) {
        requestInfo.status = 'cached';
        requestInfo.result = cached.data;
        return Promise.resolve(cached.data);
      }
    }
    
    // 添加到相应优先级的队列
    this.queues[priority].push(requestInfo);
    
    // 如果是离线状态且启用了离线队列
    if (!this.isOnline && this.options.offlineQueueEnabled && offlineFallback) {
      this.offlineQueue.push(requestInfo);
      return Promise.reject(new Error('Offline - request queued'));
    }
    
    // 返回Promise
    return new Promise((resolve, reject) => {
      requestInfo.resolve = resolve;
      requestInfo.reject = reject;
      
      // 记录请求统计
      this.recordRequestStat(requestInfo);
    });
  }
  
  // 处理队列
  processQueues() {
    // 检查是否有空闲槽位
    const availableSlots = this.options.maxConcurrent - this.activeRequests.size;
    if (availableSlots <= 0) return;
    
    // 按优先级处理队列
    for (const priority of this.options.priorityLevels) {
      const queue = this.queues[priority];
      
      while (queue.length > 0 && availableSlots > 0) {
        const requestInfo = queue.shift();
        
        // 跳过已取消的请求
        if (requestInfo.status === 'cancelled') continue;
        
        // 标记为调度中
        requestInfo.status = 'scheduled';
        requestInfo.scheduledAt = Date.now();
        
        // 执行请求
        this.executeRequest(requestInfo);
      }
    }
  }
  
  // 执行请求
  async executeRequest(requestInfo) {
    this.activeRequests.add(requestInfo.id);
    
    try {
      // 设置超时
      const timeoutPromise = new Promise((_, reject) => {
        setTimeout(() => {
          reject(new Error(`Request timeout after ${requestInfo.timeout}ms`));
        }, requestInfo.timeout);
      });
      
      // 执行请求
      const requestPromise = requestInfo.request();
      const result = await Promise.race([requestPromise, timeoutPromise]);
      
      // 请求成功
      requestInfo.status = 'completed';
      requestInfo.completedAt = Date.now();
      requestInfo.result = result;
      
      // 缓存结果
      if (this.options.cacheEnabled && requestInfo.cacheKey) {
        this.requestCache.set(requestInfo.cacheKey, {
          data: result,
          timestamp: Date.now(),
          ttl: requestInfo.options.cacheTTL || 300000 // 默认5分钟
        });
      }
      
      // 解析Promise
      if (requestInfo.resolve) {
        requestInfo.resolve(result);
      }
      
      // 清理
      this.cleanupRequest(requestInfo);
    } catch (error) {
      // 处理错误
      await this.handleRequestError(requestInfo, error);
    } finally {
      this.activeRequests.delete(requestInfo.id);
    }
  }
  
  // 处理请求错误
  async handleRequestError(requestInfo, error) {
    requestInfo.lastError = error;
    
    // 检查是否需要重试
    if (this.options.retryEnabled && this.shouldRetry(requestInfo, error)) {
      requestInfo.retryCount++;
      requestInfo.status = 'retrying';
      
      // 计算重试延迟
      const delay = this.calculateRetryDelay(requestInfo);
      
      // 延迟后重新加入队列
      setTimeout(() => {
        requestInfo.status = 'pending';
        this.queues[requestInfo.priority].push(requestInfo);
      }, delay);
      
      return;
    }
    
    // 重试次数用完或不需要重试
    requestInfo.status = 'failed';
    requestInfo.completedAt = Date.now();
    
    // 如果是离线相关错误,加入离线队列
    if (!this.isOnline && requestInfo.offlineFallback) {
      this.offlineQueue.push(requestInfo);
    }
    
    // 拒绝Promise
    if (requestInfo.reject) {
      requestInfo.reject(error);
    }
    
    // 清理
    this.cleanupRequest(requestInfo);
  }
  
  // 检查是否需要重试
  shouldRetry(requestInfo, error) {
    const strategy = this.retryStrategies.get(requestInfo.retryStrategy) || 
                    this.retryStrategies.get('default');
    
    // 检查重试次数
    if (requestInfo.retryCount >= strategy.maxRetries) {
      return false;
    }
    
    // 检查错误类型
    const errorType = this.getErrorType(error);
    
    if (strategy.retryableErrors.includes(errorType)) {
      return true;
    }
    
    // 检查HTTP状态码
    if (error.response && error.response.status) {
      return strategy.retryableStatuses.includes(error.response.status);
    }
    
    return false;
  }
  
  // 计算重试延迟(指数退避)
  calculateRetryDelay(requestInfo) {
    const strategy = this.retryStrategies.get(requestInfo.retryStrategy) || 
                    this.retryStrategies.get('default');
    
    const baseDelay = strategy.baseDelay;
    const multiplier = strategy.backoffMultiplier;
    const maxDelay = strategy.maxDelay;
    
    const delay = baseDelay * Math.pow(multiplier, requestInfo.retryCount - 1);
    
    // 添加随机抖动(防止惊群效应)
    const jitter = delay * 0.1 * (Math.random() * 2 - 1);
    
    return Math.min(delay + jitter, maxDelay);
  }
  
  // 处理离线队列
  async processOfflineQueue() {
    if (!this.isOnline || this.offlineQueue.length === 0) return;
    
    console.log(`Processing ${this.offlineQueue.length} queued offline requests`);
    
    // 复制队列并清空原队列
    const queueToProcess = [...this.offlineQueue];
    this.offlineQueue = [];
    
    // 处理队列中的请求
    for (const requestInfo of queueToProcess) {
      requestInfo.status = 'pending';
      this.queues[requestInfo.priority].push(requestInfo);
    }
  }
  
  // 清理请求
  cleanupRequest(requestInfo) {
    // 更新统计信息
    this.updateRequestStats(requestInfo);
    
    // 从统计中移除旧记录
    this.cleanupOldStats();
  }
  
  // 记录请求统计
  recordRequestStat(requestInfo) {
    if (!this.requestStats.has(requestInfo.id)) {
      this.requestStats.set(requestInfo.id, {
        id: requestInfo.id,
        priority: requestInfo.priority,
        createdAt: requestInfo.createdAt,
        completedAt: null,
        duration: null,
        status: 'pending',
        retryCount: 0,
        group: requestInfo.group
      });
    }
  }
  
  // 更新请求统计
  updateRequestStats(requestInfo) {
    const stat = this.requestStats.get(requestInfo.id);
    if (stat) {
      stat.status = requestInfo.status;
      stat.retryCount = requestInfo.retryCount;
      stat.completedAt = requestInfo.completedAt;
      
      if (requestInfo.completedAt && requestInfo.createdAt) {
        stat.duration = requestInfo.completedAt - requestInfo.createdAt;
      }
    }
  }
  
  // 清理旧统计
  cleanupOldStats() {
    const oneHourAgo = Date.now() - (60 * 60 * 1000);
    
    for (const [id, stat] of this.requestStats.entries()) {
      if (stat.createdAt < oneHourAgo) {
        this.requestStats.delete(id);
      }
    }
  }
  
  // 生成请求ID
  generateRequestId(request, options) {
    const requestString = request.toString();
    const optionsString = JSON.stringify(options);
    
    return `req_${Date.now()}_${this.hashString(requestString + optionsString)}`;
  }
  
  // 简单的哈希函数
  hashString(str) {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash;
    }
    return hash.toString(36);
  }
  
  // 获取错误类型
  getErrorType(error) {
    if (error.code) return error.code;
    if (error.name) return error.name;
    if (error.message && error.message.includes('timeout')) return 'ETIMEDOUT';
    if (error.message && error.message.includes('network')) return 'NETWORK_ERROR';
    return 'UNKNOWN_ERROR';
  }
  
  // 检查缓存是否过期
  isCacheExpired(cacheEntry) {
    if (!cacheEntry.ttl) return false;
    return Date.now() > cacheEntry.timestamp + cacheEntry.ttl;
  }
  
  // 获取调度器状态
  getStatus() {
    const pendingRequests = Object.values(this.queues)
      .reduce((sum, queue) => sum + queue.length, 0);
    
    const stats = Array.from(this.requestStats.values());
    
    const successCount = stats.filter(s => s.status === 'completed').length;
    const failedCount = stats.filter(s => s.status === 'failed').length;
    const retryCount = stats.reduce((sum, s) => sum + s.retryCount, 0);
    const avgDuration = stats
      .filter(s => s.duration)
      .reduce((sum, s) => sum + s.duration, 0) / 
      Math.max(1, stats.filter(s => s.duration).length);
    
    return {
      isOnline: this.isOnline,
      activeRequests: this.activeRequests.size,
      pendingRequests,
      offlineQueue: this.offlineQueue.length,
      cacheSize: this.requestCache.size,
      totalProcessed: stats.length,
      successRate: stats.length > 0 ? (successCount / stats.length) * 100 : 0,
      averageRetries: stats.length > 0 ? (retryCount / stats.length) : 0,
      averageDuration: avgDuration,
      queueSizes: {
        high: this.queues.high.length,
        normal: this.queues.normal.length,
        low: this.queues.low.length
      }
    };
  }
  
  // 取消请求
  cancelRequest(requestId) {
    // 查找并标记请求为取消状态
    for (const priority of this.options.priorityLevels) {
      const queue = this.queues[priority];
      const index = queue.findIndex(req => req.id === requestId);
      
      if (index !== -1) {
        const requestInfo = queue[index];
        requestInfo.status = 'cancelled';
        
        if (requestInfo.reject) {
          requestInfo.reject(new RequestCancellationError('Request cancelled'));
        }
        
        queue.splice(index, 1);
        return true;
      }
    }
    
    // 检查离线队列
    const offlineIndex = this.offlineQueue.findIndex(req => req.id === requestId);
    if (offlineIndex !== -1) {
      const requestInfo = this.offlineQueue[offlineIndex];
      requestInfo.status = 'cancelled';
      
      if (requestInfo.reject) {
        requestInfo.reject(new RequestCancellationError('Request cancelled'));
      }
      
      this.offlineQueue.splice(offlineIndex, 1);
      return true;
    }
    
    return false;
  }
  
  // 清空缓存
  clearCache() {
    this.requestCache.clear();
  }
}

// 使用示例
class SchedulerExample {
  static async demonstrate() {
    const scheduler = new IntelligentRequestScheduler({
      maxConcurrent: 3,
      priorityLevels: ['high', 'normal', 'low']
    });
    
    // 创建一些请求函数
    const createRequest = (id, delay = 1000) => async () => {
      console.log(`Starting request ${id}`);
      await new Promise(resolve => setTimeout(resolve, delay));
      console.log(`Completed request ${id}`);
      return { id, data: `Result from request ${id}` };
    };
    
    // 调度不同优先级的请求
    const requests = [
      scheduler.schedule(createRequest('high_1', 500), {
        priority: 'high',
        retryStrategy: 'critical',
        cacheKey: 'request_high_1'
      }),
      
      scheduler.schedule(createRequest('normal_1', 1000), {
        priority: 'normal',
        cacheKey: 'request_normal_1'
      }),
      
      scheduler.schedule(createRequest('low_1', 1500), {
        priority: 'low',
        retryStrategy: 'non-critical'
      }),
      
      scheduler.schedule(createRequest('high_2', 200), {
        priority: 'high',
        offlineFallback: true
      })
    ];
    
    try {
      const results = await Promise.all(requests);
      console.log('All requests completed:', results);
    } catch (error) {
      console.error('Some requests failed:', error);
    }
    
    // 获取调度器状态
    const status = scheduler.getStatus();
    console.log('Scheduler status:', status);
    
    return scheduler;
  }
}

四、WebSocket高级封装

4.1 完整的WebSocket客户端
javascript 复制代码
class WebSocketClient {
  constructor(url, options = {}) {
    this.url = url;
    this.options = {
      protocols: [],
      reconnect: true,
      maxReconnectAttempts: 5,
      reconnectDelay: 1000,
      heartbeatEnabled: true,
      heartbeatInterval: 30000,
      autoConnect: true,
      binaryType: 'blob',
      ...options
    };
    
    this.socket = null;
    this.reconnectAttempts = 0;
    this.messageQueue = [];
    this.listeners = new Map();
    this.heartbeatInterval = null;
    this.reconnectTimeout = null;
    this.isConnected = false;
    this.isConnecting = false;
    this.connectionId = null;
    
    // 事件类型
    this.EVENTS = {
      OPEN: 'open',
      CLOSE: 'close',
      MESSAGE: 'message',
      ERROR: 'error',
      RECONNECT: 'reconnect',
      HEARTBEAT: 'heartbeat'
    };
    
    if (this.options.autoConnect) {
      this.connect();
    }
  }
  
  // 连接WebSocket
  connect() {
    if (this.isConnected || this.isConnecting) {
      console.warn('WebSocket is already connected or connecting');
      return;
    }
    
    this.isConnecting = true;
    
    try {
      this.socket = new WebSocket(this.url, this.options.protocols);
      this.socket.binaryType = this.options.binaryType;
      
      this.setupEventListeners();
      
      // 设置连接超时
      setTimeout(() => {
        if (this.isConnecting && !this.isConnected) {
          console.warn('WebSocket connection timeout');
          this.handleConnectionError(new Error('Connection timeout'));
        }
      }, 10000);
    } catch (error) {
      this.handleConnectionError(error);
    }
  }
  
  // 设置事件监听器
  setupEventListeners() {
    this.socket.onopen = (event) => {
      this.isConnected = true;
      this.isConnecting = false;
      this.reconnectAttempts = 0;
      this.connectionId = this.generateConnectionId();
      
      console.log(`WebSocket connected: ${this.url}`);
      
      // 触发open事件
      this.emit(this.EVENTS.OPEN, {
        connectionId: this.connectionId,
        event
      });
      
      // 启动心跳检测
      if (this.options.heartbeatEnabled) {
        this.startHeartbeat();
      }
      
      // 发送队列中的消息
      this.flushMessageQueue();
    };
    
    this.socket.onclose = (event) => {
      this.isConnected = false;
      this.isConnecting = false;
      
      console.log(`WebSocket closed: ${event.code} ${event.reason}`);
      
      // 触发close事件
      this.emit(this.EVENTS.CLOSE, {
        code: event.code,
        reason: event.reason,
        wasClean: event.wasClean,
        connectionId: this.connectionId
      });
      
      // 停止心跳检测
      this.stopHeartbeat();
      
      // 尝试重连
      if (this.options.reconnect && !event.wasClean) {
        this.attemptReconnect();
      }
    };
    
    this.socket.onmessage = (event) => {
      // 处理心跳响应
      if (this.isHeartbeatMessage(event.data)) {
        this.emit(this.EVENTS.HEARTBEAT, { timestamp: Date.now() });
        return;
      }
      
      // 触发message事件
      this.emit(this.EVENTS.MESSAGE, {
        data: event.data,
        origin: event.origin,
        connectionId: this.connectionId,
        timestamp: Date.now()
      });
    };
    
    this.socket.onerror = (event) => {
      console.error('WebSocket error:', event);
      
      // 触发error事件
      this.emit(this.EVENTS.ERROR, {
        error: event,
        connectionId: this.connectionId
      });
      
      this.handleConnectionError(new Error('WebSocket error'));
    };
  }
  
  // 发送消息
  send(data, options = {}) {
    const {
      queueIfNotConnected = true,
      retry = false,
      maxRetries = 3,
      retryDelay = 1000
    } = options;
    
    // 如果未连接且允许排队
    if (!this.isConnected && queueIfNotConnected) {
      this.messageQueue.push({ data, options, retryCount: 0 });
      return Promise.reject(new Error('WebSocket not connected, message queued'));
    }
    
    // 如果未连接且不允许排队
    if (!this.isConnected && !queueIfNotConnected) {
      return Promise.reject(new Error('WebSocket not connected'));
    }
    
    return new Promise((resolve, reject) => {
      try {
        this.socket.send(data);
        resolve();
      } catch (error) {
        if (retry && (options.retryCount || 0) < maxRetries) {
          const retryCount = (options.retryCount || 0) + 1;
          
          setTimeout(() => {
            this.send(data, { ...options, retryCount })
              .then(resolve)
              .catch(reject);
          }, retryDelay);
        } else {
          reject(error);
        }
      }
    });
  }
  
  // 发送JSON消息
  sendJson(data, options = {}) {
    const jsonString = JSON.stringify(data);
    return this.send(jsonString, options);
  }
  
  // 发送带请求-响应模式的消息
  async sendWithResponse(data, options = {}) {
    const {
      timeout = 30000,
      responseType = 'json'
    } = options;
    
    return new Promise((resolve, reject) => {
      // 生成唯一的消息ID
      const messageId = this.generateMessageId();
      
      // 创建超时定时器
      const timeoutId = setTimeout(() => {
        this.off(messageId);
        reject(new Error('Response timeout'));
      }, timeout);
      
      // 监听特定消息ID的响应
      this.once(messageId, (response) => {
        clearTimeout(timeoutId);
        
        // 根据类型解析响应
        let parsedResponse;
        try {
          if (responseType === 'json') {
            parsedResponse = JSON.parse(response.data);
          } else if (responseType === 'text') {
            parsedResponse = response.data;
          } else {
            parsedResponse = response.data;
          }
          
          resolve(parsedResponse);
        } catch (error) {
          reject(new Error(`Failed to parse response: ${error.message}`));
        }
      });
      
      // 发送消息(包含消息ID)
      const message = {
        id: messageId,
        data,
        timestamp: Date.now()
      };
      
      this.sendJson(message).catch(reject);
    });
  }
  
  // 发送RPC调用
  async call(method, params, options = {}) {
    const rpcRequest = {
      jsonrpc: '2.0',
      method,
      params,
      id: this.generateMessageId()
    };
    
    return this.sendWithResponse(rpcRequest, options);
  }
  
  // 发送二进制数据
  sendBinary(data, options = {}) {
    let binaryData;
    
    if (data instanceof ArrayBuffer) {
      binaryData = data;
    } else if (data instanceof Blob) {
      binaryData = data;
    } else if (ArrayBuffer.isView(data)) {
      binaryData = data.buffer;
    } else {
      throw new Error('Unsupported binary data type');
    }
    
    return this.send(binaryData, options);
  }
  
  // 处理连接错误
  handleConnectionError(error) {
    this.isConnecting = false;
    this.isConnected = false;
    
    console.error('WebSocket connection error:', error);
    
    if (this.options.reconnect) {
      this.attemptReconnect();
    }
  }
  
  // 尝试重连
  attemptReconnect() {
    if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
      console.error('Max reconnection attempts reached');
      return;
    }
    
    this.reconnectAttempts++;
    
    console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})...`);
    
    this.emit(this.EVENTS.RECONNECT, {
      attempt: this.reconnectAttempts,
      maxAttempts: this.options.maxReconnectAttempts
    });
    
    // 计算重连延迟(指数退避)
    const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
    
    // 添加随机抖动
    const jitter = delay * 0.1 * (Math.random() * 2 - 1);
    
    this.reconnectTimeout = setTimeout(() => {
      this.connect();
    }, delay + jitter);
  }
  
  // 启动心跳检测
  startHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
    }
    
    this.heartbeatInterval = setInterval(() => {
      if (this.isConnected) {
        this.send('__HEARTBEAT__').catch((error) => {
          console.warn('Heartbeat failed:', error);
          this.handleConnectionError(new Error('Heartbeat failed'));
        });
      }
    }, this.options.heartbeatInterval);
  }
  
  // 停止心跳检测
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
  }
  
  // 检查是否是心跳消息
  isHeartbeatMessage(data) {
    return data === '__HEARTBEAT__' || data === '__HEARTBEAT_RESPONSE__';
  }
  
  // 清空消息队列
  flushMessageQueue() {
    while (this.messageQueue.length > 0) {
      const { data, options, retryCount } = this.messageQueue.shift();
      
      this.send(data, { ...options, retryCount }).catch((error) => {
        console.warn('Failed to send queued message:', error);
      });
    }
  }
  
  // 断开连接
  disconnect(code = 1000, reason = 'Normal closure') {
    // 清除重连定时器
    if (this.reconnectTimeout) {
      clearTimeout(this.reconnectTimeout);
      this.reconnectTimeout = null;
    }
    
    // 停止心跳检测
    this.stopHeartbeat();
    
    // 关闭WebSocket
    if (this.socket) {
      this.socket.close(code, reason);
    }
    
    this.isConnected = false;
    this.isConnecting = false;
  }
  
  // 事件监听
  on(event, listener) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, new Set());
    }
    
    this.listeners.get(event).add(listener);
    
    // 返回取消监听的函数
    return () => this.off(event, listener);
  }
  
  // 一次性事件监听
  once(event, listener) {
    const onceListener = (...args) => {
      this.off(event, onceListener);
      listener(...args);
    };
    
    return this.on(event, onceListener);
  }
  
  // 移除事件监听
  off(event, listener) {
    if (this.listeners.has(event)) {
      this.listeners.get(event).delete(listener);
      
      if (this.listeners.get(event).size === 0) {
        this.listeners.delete(event);
      }
    }
  }
  
  // 触发事件
  emit(event, data) {
    if (this.listeners.has(event)) {
      this.listeners.get(event).forEach(listener => {
        try {
          listener(data);
        } catch (error) {
          console.error(`Error in event listener for "${event}":`, error);
        }
      });
    }
    
    // 触发通配符监听器
    if (this.listeners.has('*')) {
      this.listeners.get('*').forEach(listener => {
        try {
          listener(event, data);
        } catch (error) {
          console.error('Error in wildcard event listener:', error);
        }
      });
    }
  }
  
  // 生成连接ID
  generateConnectionId() {
    return `conn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  
  // 生成消息ID
  generateMessageId() {
    return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  
  // 获取连接状态
  getStatus() {
    return {
      url: this.url,
      isConnected: this.isConnected,
      isConnecting: this.isConnecting,
      connectionId: this.connectionId,
      reconnectAttempts: this.reconnectAttempts,
      maxReconnectAttempts: this.options.maxReconnectAttempts,
      queuedMessages: this.messageQueue.length,
      binaryType: this.options.binaryType
    };
  }
  
  // 设置二进制类型
  setBinaryType(binaryType) {
    this.options.binaryType = binaryType;
    
    if (this.socket) {
      this.socket.binaryType = binaryType;
    }
  }
}

// WebSocket管理类(多连接管理)
class WebSocketManager {
  constructor() {
    this.connections = new Map();
    this.defaultOptions = {
      reconnect: true,
      maxReconnectAttempts: 3,
      reconnectDelay: 1000,
      heartbeatEnabled: true,
      heartbeatInterval: 30000
    };
  }
  
  // 创建连接
  createConnection(url, options = {}) {
    const connectionId = this.generateConnectionId(url);
    
    if (this.connections.has(connectionId)) {
      console.warn(`Connection already exists: ${connectionId}`);
      return this.connections.get(connectionId);
    }
    
    const mergedOptions = { ...this.defaultOptions, ...options };
    const client = new WebSocketClient(url, mergedOptions);
    
    this.connections.set(connectionId, client);
    
    // 监听连接关闭事件以清理
    client.on('close', () => {
      // 可以在这里执行清理操作
    });
    
    return client;
  }
  
  // 获取连接
  getConnection(connectionId) {
    return this.connections.get(connectionId);
  }
  
  // 关闭连接
  closeConnection(connectionId, code = 1000, reason = 'Normal closure') {
    const client = this.connections.get(connectionId);
    
    if (client) {
      client.disconnect(code, reason);
      this.connections.delete(connectionId);
      return true;
    }
    
    return false;
  }
  
  // 关闭所有连接
  closeAllConnections(code = 1000, reason = 'Normal closure') {
    this.connections.forEach((client, connectionId) => {
      client.disconnect(code, reason);
    });
    
    this.connections.clear();
  }
  
  // 广播消息到所有连接
  broadcast(data, options = {}) {
    const promises = [];
    
    this.connections.forEach(client => {
      if (client.isConnected) {
        promises.push(client.send(data, options));
      }
    });
    
    return Promise.allSettled(promises);
  }
  
  // 生成连接ID
  generateConnectionId(url) {
    const urlObj = new URL(url);
    const host = urlObj.host;
    const path = urlObj.pathname;
    
    return `${host}${path}`.replace(/[^a-z0-9]/gi, '_');
  }
  
  // 获取连接状态
  getStatus() {
    const status = {
      totalConnections: this.connections.size,
      connectedConnections: 0,
      connectingConnections: 0,
      connections: []
    };
    
    this.connections.forEach((client, connectionId) => {
      const clientStatus = client.getStatus();
      
      if (clientStatus.isConnected) {
        status.connectedConnections++;
      } else if (clientStatus.isConnecting) {
        status.connectingConnections++;
      }
      
      status.connections.push({
        connectionId,
        ...clientStatus
      });
    });
    
    return status;
  }
}

// 使用示例
class WebSocketExample {
  static demonstrate() {
    // 创建WebSocket客户端
    const wsClient = new WebSocketClient('wss://echo.websocket.org', {
      reconnect: true,
      maxReconnectAttempts: 3,
      heartbeatEnabled: true
    });
    
    // 监听事件
    wsClient.on('open', (event) => {
      console.log('WebSocket opened:', event.connectionId);
      
      // 发送消息
      wsClient.sendJson({ type: 'greeting', message: 'Hello WebSocket!' });
    });
    
    wsClient.on('message', (event) => {
      console.log('Received message:', event.data);
    });
    
    wsClient.on('close', (event) => {
      console.log('WebSocket closed:', event.code, event.reason);
    });
    
    wsClient.on('error', (event) => {
      console.error('WebSocket error:', event.error);
    });
    
    // 发送请求-响应模式的消息
    wsClient.sendWithResponse({ type: 'ping' })
      .then(response => console.log('Response:', response))
      .catch(error => console.error('Request failed:', error));
    
    // 获取状态
    const status = wsClient.getStatus();
    console.log('WebSocket status:', status);
    
    return wsClient;
  }
}
4.2 WebSocket重连与消息可靠性
javascript 复制代码
class ReliableWebSocket extends WebSocketClient {
  constructor(url, options = {}) {
    const defaultOptions = {
      messageRetention: true,
      maxMessageQueueSize: 1000,
      messageExpiry: 5 * 60 * 1000, // 5分钟
      deliveryGuarantee: 'at-least-once', // 'at-most-once', 'at-least-once', 'exactly-once'
      requireAcknowledgement: false,
      acknowledgementTimeout: 5000,
      ...options
    };
    
    super(url, defaultOptions);
    
    this.pendingMessages = new Map();
    this.acknowledgedMessages = new Set();
    this.messageSequence = 0;
    this.lastAcknowledgedSequence = 0;
    this.acknowledgementTimeouts = new Map();
    
    // 设置消息确认监听
    this.setupAcknowledgementListener();
  }
  
  // 发送可靠消息
  async sendReliable(data, options = {}) {
    const {
      requireAcknowledgement = this.options.requireAcknowledgement,
      acknowledgementTimeout = this.options.acknowledgementTimeout,
      maxRetries = 3,
      retryDelay = 1000
    } = options;
    
    // 生成消息ID和序列号
    const messageId = this.generateMessageId();
    const sequenceNumber = this.messageSequence++;
    
    // 创建消息对象
    const message = {
      id: messageId,
      seq: sequenceNumber,
      data,
      timestamp: Date.now(),
      retryCount: 0,
      status: 'pending'
    };
    
    // 如果需要确认,添加到待处理消息列表
    if (requireAcknowledgement) {
      this.pendingMessages.set(messageId, message);
      
      // 设置确认超时
      this.setAcknowledgementTimeout(messageId, acknowledgementTimeout);
    }
    
    // 封装发送的消息
    const wrappedMessage = {
      type: 'data',
      reliable: requireAcknowledgement,
      messageId,
      sequenceNumber,
      data
    };
    
    try {
      await this.sendJson(wrappedMessage);
      message.status = 'sent';
      
      // 如果需要确认,等待确认
      if (requireAcknowledgement) {
        return this.waitForAcknowledgement(messageId, acknowledgementTimeout);
      }
      
      return Promise.resolve({ messageId, status: 'sent' });
    } catch (error) {
      message.status = 'failed';
      message.error = error;
      
      // 重试逻辑
      if (maxRetries > 0) {
        return this.retrySendReliable(message, {
          maxRetries,
          retryDelay,
          requireAcknowledgement
        });
      }
      
      throw error;
    }
  }
  
  // 等待消息确认
  waitForAcknowledgement(messageId, timeout) {
    return new Promise((resolve, reject) => {
      // 检查是否已经确认
      if (this.acknowledgedMessages.has(messageId)) {
        resolve({ messageId, status: 'acknowledged' });
        return;
      }
      
      // 设置超时
      const timeoutId = setTimeout(() => {
        const message = this.pendingMessages.get(messageId);
        
        if (message) {
          message.status = 'timeout';
          this.pendingMessages.delete(messageId);
        }
        
        reject(new Error(`Acknowledgement timeout for message ${messageId}`));
      }, timeout);
      
      // 监听确认事件
      const acknowledgementListener = (ack) => {
        if (ack.messageId === messageId) {
          clearTimeout(timeoutId);
          this.off('acknowledgement', acknowledgementListener);
          resolve({ messageId, status: 'acknowledged' });
        }
      };
      
      this.on('acknowledgement', acknowledgementListener);
    });
  }
  
  // 重试发送可靠消息
  async retrySendReliable(message, options) {
    const {
      maxRetries,
      retryDelay,
      requireAcknowledgement
    } = options;
    
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      message.retryCount = attempt;
      message.status = 'retrying';
      
      console.log(`Retrying message ${message.id} (attempt ${attempt}/${maxRetries})`);
      
      // 等待重试延迟
      await new Promise(resolve => setTimeout(resolve, retryDelay * attempt));
      
      try {
        const wrappedMessage = {
          type: 'data',
          reliable: requireAcknowledgement,
          messageId: message.id,
          sequenceNumber: message.seq,
          data: message.data,
          retry: attempt
        };
        
        await this.sendJson(wrappedMessage);
        message.status = 'sent';
        
        // 如果需要确认,等待确认
        if (requireAcknowledgement) {
          const result = await this.waitForAcknowledgement(
            message.id,
            this.options.acknowledgementTimeout
          );
          
          return result;
        }
        
        return { messageId: message.id, status: 'sent' };
      } catch (error) {
        message.status = 'failed';
        message.error = error;
        
        if (attempt === maxRetries) {
          throw error;
        }
      }
    }
    
    throw new Error(`Failed to send message after ${maxRetries} retries`);
  }
  
  // 设置确认超时
  setAcknowledgementTimeout(messageId, timeout) {
    const timeoutId = setTimeout(() => {
      const message = this.pendingMessages.get(messageId);
      
      if (message && message.status !== 'acknowledged') {
        console.warn(`Acknowledgement timeout for message ${messageId}`);
        
        // 触发超时事件
        this.emit('acknowledgement_timeout', {
          messageId,
          message,
          timestamp: Date.now()
        });
        
        this.pendingMessages.delete(messageId);
      }
      
      this.acknowledgementTimeouts.delete(messageId);
    }, timeout);
    
    this.acknowledgementTimeouts.set(messageId, timeoutId);
  }
  
  // 清理确认超时
  clearAcknowledgementTimeout(messageId) {
    const timeoutId = this.acknowledgementTimeouts.get(messageId);
    
    if (timeoutId) {
      clearTimeout(timeoutId);
      this.acknowledgementTimeouts.delete(messageId);
    }
  }
  
  // 设置消息确认监听器
  setupAcknowledgementListener() {
    // 监听确认消息
    this.on('message', (event) => {
      try {
        const message = JSON.parse(event.data);
        
        if (message.type === 'acknowledgement') {
          this.handleAcknowledgement(message);
        } else if (message.type === 'data' && message.reliable) {
          // 收到可靠消息,发送确认
          this.sendAcknowledgement(message.messageId, message.sequenceNumber);
        }
      } catch (error) {
        // 不是JSON消息,忽略
      }
    });
    
    // 监听连接打开事件,重新发送未确认的消息
    this.on('open', () => {
      this.resendUnacknowledgedMessages();
    });
  }
  
  // 处理确认消息
  handleAcknowledgement(ackMessage) {
    const { messageId, sequenceNumber } = ackMessage;
    
    // 清理确认超时
    this.clearAcknowledgementTimeout(messageId);
    
    // 更新最后确认的序列号
    if (sequenceNumber > this.lastAcknowledgedSequence) {
      this.lastAcknowledgedSequence = sequenceNumber;
    }
    
    // 从待处理消息中移除
    const message = this.pendingMessages.get(messageId);
    if (message) {
      message.status = 'acknowledged';
      message.acknowledgedAt = Date.now();
      this.pendingMessages.delete(messageId);
    }
    
    // 添加到已确认消息集合
    this.acknowledgedMessages.add(messageId);
    
    // 触发确认事件
    this.emit('acknowledgement', {
      messageId,
      sequenceNumber,
      timestamp: Date.now(),
      message
    });
    
    // 清理过期的已确认消息
    this.cleanupAcknowledgedMessages();
  }
  
  // 发送确认消息
  sendAcknowledgement(messageId, sequenceNumber) {
    const ackMessage = {
      type: 'acknowledgement',
      messageId,
      sequenceNumber,
      timestamp: Date.now()
    };
    
    this.sendJson(ackMessage).catch(error => {
      console.warn('Failed to send acknowledgement:', error);
    });
  }
  
  // 重新发送未确认的消息
  resendUnacknowledgedMessages() {
    const now = Date.now();
    const unacknowledged = [];
    
    // 收集未确认的消息
    this.pendingMessages.forEach((message, messageId) => {
      // 检查消息是否过期
      if (now - message.timestamp > this.options.messageExpiry) {
        console.log(`Message ${messageId} expired, removing`);
        this.pendingMessages.delete(messageId);
        this.clearAcknowledgementTimeout(messageId);
        return;
      }
      
      // 检查消息是否需要重发
      if (message.status === 'sent' || message.status === 'pending') {
        unacknowledged.push(message);
      }
    });
    
    // 重新发送未确认的消息
    unacknowledged.forEach(message => {
      console.log(`Resending unacknowledged message ${message.id}`);
      
      const wrappedMessage = {
        type: 'data',
        reliable: true,
        messageId: message.id,
        sequenceNumber: message.seq,
        data: message.data,
        resent: true
      };
      
      this.sendJson(wrappedMessage).catch(error => {
        console.warn(`Failed to resend message ${message.id}:`, error);
      });
    });
  }
  
  // 清理已确认的消息
  cleanupAcknowledgedMessages() {
    const maxSize = 1000; // 最多保留1000个已确认消息
    
    if (this.acknowledgedMessages.size > maxSize) {
      // 转换为数组,排序,删除最旧的
      const sorted = Array.from(this.acknowledgedMessages)
        .slice(-maxSize);
      
      this.acknowledgedMessages = new Set(sorted);
    }
  }
  
  // 覆盖父类的send方法,添加可靠性支持
  send(data, options = {}) {
    const { reliable = false, ...sendOptions } = options;
    
    if (reliable) {
      return this.sendReliable(data, sendOptions);
    }
    
    return super.send(data, sendOptions);
  }
  
  // 覆盖父类的sendJson方法
  sendJson(data, options = {}) {
    const { reliable = false, ...sendOptions } = options;
    
    if (reliable) {
      return this.sendReliable(data, sendOptions);
    }
    
    return super.sendJson(data, sendOptions);
  }
  
  // 获取可靠消息统计
  getReliabilityStats() {
    const now = Date.now();
    let pendingCount = 0;
    let acknowledgedCount = 0;
    let failedCount = 0;
    let expiredCount = 0;
    
    this.pendingMessages.forEach(message => {
      if (now - message.timestamp > this.options.messageExpiry) {
        expiredCount++;
      } else if (message.status === 'acknowledged') {
        acknowledgedCount++;
      } else if (message.status === 'failed') {
        failedCount++;
      } else {
        pendingCount++;
      }
    });
    
    return {
      pendingMessages: pendingCount,
      acknowledgedMessages: this.acknowledgedMessages.size,
      failedMessages: failedCount,
      expiredMessages: expiredCount,
      totalSentMessages: this.messageSequence,
      lastAcknowledgedSequence: this.lastAcknowledgedSequence,
      messageQueueSize: this.messageQueue.length,
      acknowledgementTimeouts: this.acknowledgementTimeouts.size
    };
  }
  
  // 清理所有待处理消息
  cleanupAllMessages() {
    this.pendingMessages.clear();
    this.acknowledgedMessages.clear();
    this.messageQueue = [];
    
    // 清理所有超时定时器
    this.acknowledgementTimeouts.forEach(timeoutId => {
      clearTimeout(timeoutId);
    });
    
    this.acknowledgementTimeouts.clear();
  }
}

// 使用示例
class ReliableWebSocketExample {
  static demonstrate() {
    // 创建可靠WebSocket客户端
    const reliableWs = new ReliableWebSocket('wss://echo.websocket.org', {
      requireAcknowledgement: true,
      acknowledgementTimeout: 3000,
      messageExpiry: 60000, // 1分钟
      reconnect: true
    });
    
    // 监听确认事件
    reliableWs.on('acknowledgement', (ack) => {
      console.log('Message acknowledged:', ack.messageId);
    });
    
    reliableWs.on('acknowledgement_timeout', (timeout) => {
      console.warn('Acknowledgement timeout:', timeout.messageId);
    });
    
    // 发送可靠消息
    reliableWs.sendReliable({ type: 'test', data: 'Hello reliable WebSocket!' })
      .then(result => {
        console.log('Reliable message sent and acknowledged:', result);
      })
      .catch(error => {
        console.error('Failed to send reliable message:', error);
      });
    
    // 获取可靠性统计
    const stats = reliableWs.getReliabilityStats();
    console.log('Reliability stats:', stats);
    
    return reliableWs;
  }
}
相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax