Axios 之 ts 版本的请求封装

avatar
作者
筋斗云
阅读量:1

文章目录

1、安装

npm install axios 

文档链接:中文文档

2、常用封装

2.1 简单版本的封装

这里仅封装常用的 get、post、put、delete 几种方法
且只封装几种常见的报错提示
src/utils/request.ts

import axios, {   AxiosError,   AxiosInstance,   AxiosResponse,   InternalAxiosRequestConfig, } from "axios";  const config = {   baseURL: "http://localhost:3000/api",   timeout: 10000,   withCredentials: true,   headers: {}, };  class RequestHttp {   service: AxiosInstance;    constructor() {     this.service = axios.create(config);      /**      * @description 请求拦截器      */     this.service.interceptors.request.use(       (config: InternalAxiosRequestConfig) => {         return config;       }     );      /**      * @description 响应拦截器      */     this.service.interceptors.response.use(       (response: AxiosResponse) => {         const { data } = response;         return data;       },        (error: AxiosError) => {         const { response } = error;         if (response) {           checkStatus(response.status);         }         return false;       }     );   }    // 常用请求方法封装   get(url: string, params?: object, _object = {}) {     return this.service.get(url, { params, ..._object });   }   post(url: string, params?: object, _object = {}) {     return this.service.post(url, params, _object);   }   put(url: string, params?: object, _object = {}) {     return this.service.put(url, params, _object);   }   delete(url: string, params?: any, _object = {}) {     return this.service.delete(url, { params, ..._object });   } }  /**  * @description: 校验网络请求状态码  * @param {Number} status  * @return void  */  const checkStatus = (status: number): void => {   switch (status) {       case 404:           console.warn("资源不存在!");           break;       case 405:           console.warn("请求方式错误!");           break;       case 500:           console.warn("服务器异常!");           break;       default:           console.warn("请求失败!");   } };  const request = new RequestHttp(); export default request; 

2.1 包含多处理的封装

增加如下处理

  1. 请求loading
  2. 取消请求(CancelToken)
  3. 请求结果的更细节处理

src/utils/request.ts

import { message } from "antd"; import axios, {   AxiosInstance,   InternalAxiosRequestConfig,   AxiosResponse,   AxiosError, } from "axios"; import { store } from "@/redux"; import { ResponseCodeEnum } from "@/enums/httpEnum"; import { setToken } from "@/redux/modules/global"; import { ResultData } from "@/api/types/index.type"; import fullLoading from "./fullLoading"; import { AxiosCancel } from "./AxiosCancel";  const config = {   baseURL: "http://localhost:3000/api",   timeout: 5000,   withCredentials: true,   headers: {}, };  const axiosCancel = new AxiosCancel();  class RequestHttp {   service: AxiosInstance;    constructor() {     this.service = axios.create(config);      /**      * @description 请求拦截器      */     this.service.interceptors.request.use(       (config: InternalAxiosRequestConfig) => {         console.log(config)          // 打开全局 loading         // 如不需要全局 loading,则第三个参数  { headers: { noLoading: true } }         if(!config.headers.noLoading) {           fullLoading.show();         }          // 将请求添加到 pending 中         axiosCancel.addPending(config);          // 这里如果需要添加token         const token = store.getState().global.token; // 我这里用的是 react-redux + redux-toolkit         config.headers["X-Access-Token"] = token;          return config;       }     );      /**      * @description 响应拦截器      */     this.service.interceptors.response.use(       (response: AxiosResponse) => {         const { data, config } = response;          // 关闭全局 loading         if(!config.headers.noLoading) {           fullLoading.hide();         }          // 请求结束,移除本次请求         axiosCancel.removePending(config.url, config.method);          // 接口返回 code 不是 200 的处理         if (data.code !== ResponseCodeEnum.SUCCESS) {           message.error(data.msg);            // 登录失效,清除 token,跳转到登录页面           if (data.code === ResponseCodeEnum.NOLOGIN) {             store.dispatch(setToken(""));             window.location.href = "/login";           }            return Promise.reject(data);         }         return data;       },        (error: AxiosError) => {         fullLoading.hide();          const { response } = error;         if (response) {           checkStatus(response.status);         }         return false;       }     );   }    // 常用请求方法封装   get<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {     return this.service.get(url, { params, ..._object });   }   post<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {     return this.service.post(url, params, _object);   }   put<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {     return this.service.put(url, params, _object);   }   delete<T>(url: string, params?: any, _object = {}): Promise<ResultData<T>> {     return this.service.delete(url, { params, ..._object });   } }  /**  * @description: 校验网络请求状态码  * @param {Number} status  * @return void  */ const checkStatus = (status: number): void => {   switch (status) {     case 404:       message.error("资源不存在!");       break;     case 405:       message.error("请求方式错误!");       break;     case 500:       message.error("服务器异常!");       break;     default:       message.error("请求失败!");   } };  const request = new RequestHttp(); export default request; 

取消请求的封装:
src/utils/AxiosCancel.ts

import axios, { AxiosRequestConfig, Canceler } from "axios";  const cancelMap = new Map<string, Canceler>();  export class AxiosCancel {   /**    * 添加请求的 cancel    * @param config    */   addPending(config: AxiosRequestConfig) {     const { url, method } = config;      if (!url || !method) return;      // 处理同个api,同时多次请求的情况,先移除上一个     this.removePending(url, method);      const key = getCancelMapKey(url, method);     config.cancelToken = new axios.CancelToken((cancel: Canceler) => {       if (!cancelMap.has(key)) {         cancelMap.set(key, cancel);       }     });   }    /**    * 移除请求    * @param url    * @param method    */   removePending(url: string | undefined, method: string | undefined) {     if (!url || !method) return;          const key = getCancelMapKey(url, method);     const cancel = cancelMap.get(key);     if (cancel) {       cancel();       cancelMap.delete(key);     }   }    /**    * 移除所有请求    */   removeAllPending() {     cancelMap.forEach((cancel) => {       cancel && cancel();     });     cancelMap.clear();   } }  function getCancelMapKey(url: string, method: string) {   return `${url}_${method}`; }  

全局加载loading
src/utils/fullLoading.ts

import ReactDOM from "react-dom/client"; import { Spin } from "antd";  // 当前请求的个数 let reqCount = 0;  // 显示 loading function show() {   if (reqCount === 0) {     const dom = document.createElement("div");     dom.id = "loading";     dom.style.position = "fixed";     dom.style.top = "0";     dom.style.right = "0";     dom.style.bottom = "0";     dom.style.left = "0";     dom.style.background = "rgba(0, 0, 0, 0.5)";     dom.style.display = "flex";     dom.style.justifyContent = "center";     dom.style.alignItems = "center";     dom.style.zIndex = "9999";     document.body.appendChild(dom);     ReactDOM.createRoot(dom).render(<Spin size="large"></Spin>);   }   reqCount++; }  // 隐藏 loading function hide() {   reqCount--;   if (reqCount === 0) {     const dom = document.getElementById("loading");     if (dom) {       document.body.removeChild(dom as HTMLElement);     }   } }  const fullLoading = {   show,   hide, };  export default fullLoading; 

src/enums/httpEnum.ts

/**  * @description:响应结果枚举  */  export enum ResponseCodeEnum { 	SUCCESS = 200, 	ERROR = 500, 	NOLOGIN = 499, } 

类型文件
src/api/type/api.type.ts

// 接口返回结构,不包含 data export interface ResponseResult {   // 状态码   code: number;   // 消息   msg: string; }  // 完整的接口返回结构 export interface ResultData<T = any> extends ResponseResult {   // 数据   data: T; }  

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!