vue3 axios封装

发布于:2024-07-03 ⋅ 阅读:(14) ⋅ 点赞:(0)
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError, CancelTokenSource } from 'axios';
import { CookieHandler } from '@/utils/cookie.ts';
import { API_URL } from '@/utils/constants'
class AxiosService {
  private axiosInstance: AxiosInstance;
  private cancelTokenSources: CancelTokenSource[];

  constructor(baseURL: string = API_URL, timeout: number = 50000) {
    this.axiosInstance = axios.create({
      baseURL,
      timeout,
      headers: {
        'Content-Type': 'application/json',
      },
    });

    this.cancelTokenSources = [];
    this.setupInterceptors();
  }

  // 设置请求拦截器
  private setupInterceptors() {
    this.axiosInstance.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        this.addUserAuthentication(config);
        this.addRequestTimestamp(config);
        this.logRequest(config);
        return config;
      },
      (error: AxiosError) => Promise.reject(error)
    );
  }

  // 添加用户认证信息
  private addUserAuthentication(config: AxiosRequestConfig) {
    const userToken = CookieHandler.getCookie('userToken');
    if (userToken) {
      config.headers!['token'] = `${userToken}`;
    }
  }

  // 在请求头中添加时间戳
  private addRequestTimestamp(config: AxiosRequestConfig) {
    config.headers!['Request-Timestamp'] = new Date().toISOString();
  }

  // 记录请求日志
  private logRequest(config: AxiosRequestConfig) {
    console.log(`Making ${config.method?.toUpperCase()} request to ${config.url}`);
  }

  // 执行请求
  private async makeRequest<T>(method: string, url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    const source = axios.CancelToken.source();
    this.cancelTokenSources.push(source);

    try {
      const response: AxiosResponse<T> = await this.axiosInstance.request<T>({
        method,
        url,
        data,
        cancelToken: source.token,
        ...config,
      });

      return response.data;
    } catch (error: any) {
      if (axios.isCancel(error)) {
        console.log('Request canceled:', error.message);
        throw new Error('Request canceled');
      } else if (error.response) {
        const errorMessage = error.response.data.message || 'An error occurred';
        throw new Error(errorMessage);
      } else if (error.request) {
        throw new Error('No response received');
      } else {
        throw new Error('Error sending request');
      }
    } finally {
      this.removeCancelledRequests();
    }
  }

  // 手动触发请求方法
  public async manuallyTriggerRequest<T>(method: string, url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return await this.makeRequest<T>(method, url, data, config); // 没有缓存,直接调用
  }

  // 取消所有挂起的请求
  public async cancelRequests() {
    this.cancelTokenSources.forEach(source => source.cancel('Request canceled by user'));
  }

  // 移除已取消的请求
  private removeCancelledRequests() {
    this.cancelTokenSources = this.cancelTokenSources.filter(source => source.token.reason === undefined);
  }
  // 发送 GET 请求
  public async get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    try {
      return await this.makeRequest<T>('GET', url, undefined, config);
    } catch (error: any) {
      console.error('Error in GET request:', error.message);
      throw error;
    }
  }

  // 发送 POST 请求
  public async post<T>(url: string, data: any, config?: AxiosRequestConfig): Promise<T> {
    try {
      return await this.makeRequest<T>('POST', url, data, config);
    } catch (error: any) {
      console.error('Error in POST request:', error.message);
      throw error;
    }
  }

  // 发送 PUT 请求
  public async put<T>(url: string, data: any, config?: AxiosRequestConfig): Promise<T> {
    try {
      return await this.makeRequest<T>('PUT', url, data, config);
    } catch (error: any) {
      console.error('Error in PUT request:', error.message);
      throw error;
    }
  }

  // 发送 DELETE 请求
  public async delete<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    try {
      return await this.makeRequest<T>('DELETE', url, undefined, config);
    } catch (error: any) {
      console.error('Error in DELETE request:', error.message);
      throw error;
    }
  }

  // 发送 OPTIONS 请求并在满足条件时发送 POST 请求
  public async sendOptions<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    try {
      const response = await this.axiosInstance.request<T>({
        method: 'OPTIONS',
        url: url,
        data: data,
        ...config,
      });
      
      // 检查是否允许 POST 请求
      const allowMethods = response.headers['Access-Control-Allow-Methods'];
      if (response.status === 204 && allowMethods && allowMethods.includes('POST')) {
        // 如果收到 204 响应状态码并且允许 POST 请求,发送 POST 请求
        return await this.post<T>(url, data, config);
      }

      return response.data;
    } catch (error: any) {
      console.error('Error in OPTIONS request:', error.message);
      throw error;
    }
  }
}

export default new AxiosService();