, ,

axios简单封装

request.ts eventEmitter.ts api/interface/index.ts api/m…

request.ts

import type {
  AxiosInstance,
  AxiosRequestConfig,
  InternalAxiosRequestConfig,
  AxiosError,
  AxiosResponse
} from "axios";
import axios from "axios";
import event from "./eventEmitter";
import type { ResultData } from "./interface";

class Request {
  private service: AxiosInstance;

  constructor(config: AxiosRequestConfig) {
    this.service = axios.create(config);
    
    /** 请求拦截器 */
    this.service.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 在请求发送时处理一些内容
        // 比如在请求头中添加 token
        const token = localStorage.getItem("token");
        if (token) { 
          config.headers.Authorization = "Bearer " + token;
        }
        return config;
      },
      (error: AxiosError) => {
        return Promise.reject(error);
      }
    );
    /** 响应拦截器 */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => { 
        const { data } = response;
        
        if (data.code === RequestEnums.LOGINTIMEOUT) { 
          event.emit("API:SESSION_EXPIRED");
          return Promise.reject(data);
        }
        if (data.code !==  RequestEnums.SUCCESS) { 
          event.emit("API:INVALID");
          return Promise.reject(data);
        }
        return data;
      },
      (error: AxiosError) => { 
        event.emit("API:NETWORK_ERROR");
        return Promise.reject(error)
      }
    );
  }

  get<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.get(url, { params });
  }
  post<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.post(url, params);
  }
  put<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.put(url, params);
  }
  delete<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.delete(url, { params });
  }
}

enum RequestEnums {
  TIMEOUT = 10000, // 请求超时
  FAIL = 500, // 服务器异常
  INVALID = 400, // 参数错误
  LOGINTIMEOUT = 401, // 登录超时
  SUCCESS = 200, // 请求成功
}

const config: AxiosRequestConfig = {
  baseURL: "/api",
  timeout: RequestEnums.TIMEOUT as number,
  withCredentials: true,
};

const request = new Request(config);

export default request;

eventEmitter.ts

const eventNames = ["API:UN_AUTHORIZED", "API:INVALID", "API:NETWORK_ERROR", "API:SESSION_EXPIRED"] as const;
type EventName = typeof eventNames[number];

// 发布订阅模式
class EventEmitter { 
  private listeners: Record<EventName, Set<Function>> = {
    "API:UN_AUTHORIZED": new Set,
    "API:INVALID": new Set,
    "API:NETWORK_ERROR": new Set,
    "API:SESSION_EXPIRED": new Set
  }

  // 监听事件,和dom注册事件是一个道理,将来某个事件发生的时候需要运行哪个函数
  on(eventName: EventName, listener: Function) { 
    this.listeners[eventName].add(listener);
  }

  // 触发事件,当某个事件发生的时候,调用监听的函数
  emit(eventName: EventName, ...args: any[]) { 
    this.listeners[eventName].forEach(listener => listener(...args));
  }
}

export default new EventEmitter();

api/interface/index.ts

export interface Result { 
  code: number;
  msg: string;
  success: boolean;
}

export interface ResultData<T = any> extends Result { 
  data?: T;
}

export interface Sales{
  _id: string;
  name: string;
  value: number;
}

export interface Trends { 
  _id: string;
  name: string;
  data: number[];
}

api/modules/sales.ts

import type { Sales } from "../interface";
import request from "../request";

export const getSalesList = () => { 
  return request.get<Sales[]>('/api/sales/list');
}

Previous Post

Next Post

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About the Author

每个人都有自己得时区,在自己得时区里,一切都是准时的。

BlockSpare — News, Magazine and Blog Addons for (Gutenberg) Block Editor