用ts封装一个axios

用ts封装一个axios

前置知识

axios.create(config) 对axios请求进行二次封装

  1. 根据指定配置创建一个新的 axios ,也就是每个axios 都有自己的配置
  2. 新的 axios 只是没有 取消请求批量请求 的方法,其它所有语法都是一致的
const instance = axios.create({
    baseURL:"http://localhost:3000"
})
const instance2 = axios.create({
    baseURL:"http://localhost:4000"
})

// 同时请求 端口号 3000 4000
// 使用instance发请求
instance({
    url:"/posts"
})
// 使用instance2发请求
instance2({
    url:"/posts"
})

axios拦截器

// 添加请求拦截器
axios.interceptors.request.use(config=>{
	// config 请求配置
	// 请求成功拦截
    console.log("请求拦截器")
    return config
},err=>{
	// 请求失败拦截
    return Promise.reject(err)
})  

// 添加响应拦截器
axios.interceptors.response.use(res=>{
	// res 响应结果
	// 响应拦成功拦截
    console.log("响应拦截器")
    return res
},err=>{
	// 响应拦失败拦截
    return Promise.reject(err)
})  

axios取消请求

  1. 配置 cancelToken 对象
  2. 缓存用于取消请求的 cancel 函数
  3. 在后面特定时机调用 cancel 函数取消请求
  4. 在错误回调中判断如果 error 是cancel ,做相应处理
axios.get("http://localhost:4000",{
  cancelToken:new axios.CancelToken(function(c){
    // c 用于取消当前请求的函数
    cancel = c
  })
})
  .then(res=>{
  console.log("res:",res)
  cancel = null //请求完成,清空cancel
},err=>{
  cancel = null 
  if(err.constructor.name === 'Cancel'){ //是取消请求导致的errer
    console.log("取消请求导致error:",err)
  }else{
    console.log("err:",err)
  }
  // 或
  // axios.isCancel(err) //判断错误是否 是取消请求导致的
});

实战代码

type Method = 'GET' | 'POST' | 'PUT' | 'DELETE'
type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'

interface AxiosRequest {
    baseURL?: string;
    url: string;
    data?: any;
    params?: any;
    method?: Method;
    headers?: any;
    timeout?: number;
    responseType?: ResponseType;
}

interface CustomResponse {
    readonly status: boolean;
    readonly message: string;
    data: any;
    origin?: any;
}


import axios, { AxiosRequestConfig } from 'axios';

// 定义接口
interface PendingType {
    url?: string;
    method?: Method;
    params: any;
    data: any;
    cancel: Function;
}

// 取消重复请求
const pending: Array<PendingType> = [];
const CancelToken = axios.CancelToken;

// axios 实例
const instance = axios.create({
    timeout: 10000,
    responseType: 'json'
});

// 移除重复请求
const removePending = (config: AxiosRequestConfig) => {
    for (const key in pending) {
        const item: number = +key;
        const list: PendingType = pending[key];
        // 当前请求在数组中存在时执行函数体
        if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
            // 执行取消操作
            list.cancel('操作太频繁,请稍后再试');
            // 从数组中移除记录
            pending.splice(item, 1);
        }
    }
};

// 添加请求拦截器
instance.interceptors.request.use(
    (request:any) => {
        // TODO: handle loading

        removePending(request);
        request.cancelToken = new CancelToken((c) => {
            pending.push({ url: request.url, method: request.method, params: request.params, data: request.data, cancel: c });
        });
        return request;
    },
    (error: any) => {
        return Promise.reject(error);
    }
);
// 添加响应拦截器
instance.interceptors.response.use(
    (response: any) => {
        removePending(response.config);

        const errorCode = response?.data?.errorCode;
        switch (errorCode) {
            case '401':
                // 根据errorCode,对业务做异常处理(和后端约定)
                break;
            default:
                break;
        }

        return response;
    },
    (error: any) => {
        const response = error.response;

        // 根据返回的http状态码做不同的处理
        switch (response?.status) {
            case 401:
                // token失效
                break;
            case 403:
                // 没有权限
                break;
            case 500:
                // 服务端错误
                break;
            case 503:
                // 服务端错误
                break;
            default:
                break;
        }

        return Promise.reject(response || {message: error.message});
    }
);

class BaseHttp {
    // 外部传入的baseUrl
    protected baseURL: string = process.env.VUE_APP_BaseURL as string;
    // 自定义header头
    protected headers: object = {
        ContentType: 'application/json;charset=UTF-8'
    }

    private apiAxios({ 
        baseURL = this.baseURL, 
        headers = this.headers, 
        method, 
        url, 
        data, 
        params, 
        responseType 
    }: AxiosRequest): Promise<CustomResponse> {

        return new Promise((resolve, reject) => {
            instance({
                baseURL,
                headers,
                method,
                url,
                params,
                data,
                responseType
            }).then((res: any) => {
                // 200:服务端业务处理正常结束
                if (res.status === 200) {
                    // TODO ...
                    // resolve({});
                } else {
                    resolve({ 
                        status: false, 
                        message: res.data?.errorMessage || (url + '请求失败'), 
                        data: null 
                    });
                }
            }).catch((err: any) => {
                const message = err?.data?.errorMessage || err?.message || (url + '请求失败');
                // eslint-disable-next-line
                reject({ status: false, message, data: null});
            });
        });
    }

    /**
     * GET类型的网络请求
     */
    protected getReq({ 
        baseURL, 
        headers, 
        url, 
        data, 
        params, 
        responseType 
    }: AxiosRequest) {
        return this.apiAxios({ 
            baseURL, 
            headers, 
            method: 'GET', 
            url, 
            data, 
            params, 
            responseType 
        });
    }

    /**
     * POST类型的网络请求
     */
    protected postReq({ baseURL, headers, url, data, params, responseType }: AxiosRequest) {
        return this.apiAxios({ baseURL, headers, method: 'POST', url, data, params, responseType });
    }

    /**
     * PUT类型的网络请求
     */
    protected putReq({ baseURL, headers, url, data, params, responseType }: AxiosRequest) {
        return this.apiAxios({ baseURL, headers, method: 'PUT', url, data, params, responseType });
    }

    /**
     * DELETE类型的网络请求
     */
    protected deleteReq({ baseURL, headers, url, data, params, responseType }: AxiosRequest) {
        return this.apiAxios({ baseURL, headers, method: 'DELETE', url, data, params, responseType });
    }
}


你可能感兴趣的:(前端,学习笔记,javascript,typescript,前端)