浏览器网络请求 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;
  }
}
相关推荐
小费的部落2 小时前
Excel 在Sheet3中 匹配Sheet1的A列和Sheet2的A列并处理空内容
java·前端·excel
霍格沃兹测试学院-小舟畅学2 小时前
Cypress 入门与优势分析:前端自动化测试的新利器
前端
1024肥宅2 小时前
浏览器网络请求 API:全面解析与高级封装(2)
前端·websocket·axios
幼儿园技术家2 小时前
深入理解 CSR / SSR / SSG:前端三种渲染模式的本质与选型
前端
How_doyou_do2 小时前
常见的设计模式
前端·javascript·设计模式
3824278272 小时前
汇编:条件汇编、
前端·汇编·数据库
狗哥哥2 小时前
企业级 HTTP 客户端架构演进与设计
前端·架构
前端无涯2 小时前
react组件(4)---高阶使用及闭坑指南
前端·react.js
Gomiko2 小时前
JavaScript DOM 原生部分(五):事件绑定
开发语言·前端·javascript