用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 });
    }
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的使用Vue3和TypeScript封装Axios的示例: 1. 安装依赖 ```bash npm install axios npm install @types/axios ``` 2. 创建一个`api.ts`文件 ```typescript import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; export interface ApiResponse<T> { code: number; message: string; data: T; } class Api { private axiosInstance: AxiosInstance; constructor() { this.axiosInstance = axios.create({ baseURL: 'https://api.example.com', timeout: 10000, }); this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => { // 在请求发送之前做一些处理 return config; }); this.axiosInstance.interceptors.response.use((response: AxiosResponse) => { // 对响应数据做一些处理 return response; }, (error) => { // 对响应错误做一些处理 return Promise.reject(error); }); } public async get<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> { const response = await this.axiosInstance.get<T>(url, config); return response.data; } public async post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ApiResponse<T>> { const response = await this.axiosInstance.post<T>(url, data, config); return response.data; } public async put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ApiResponse<T>> { const response = await this.axiosInstance.put<T>(url, data, config); return response.data; } public async delete<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> { const response = await this.axiosInstance.delete<T>(url, config); return response.data; } } export default new Api(); ``` 3. 在Vue组件中使用 ```vue <template> <div> <button @click="getData">Get Data</button> <ul> <li v-for="item in data" :key="item.id">{{ item.name }} - {{ item.email }}</li> </ul> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; import api, { ApiResponse } from './api'; interface User { id: number; name: string; email: string; } export default defineComponent({ name: 'App', setup() { const data = ref<User[]>([]); const getData = async () => { const response: ApiResponse<User[]> = await api.get('/users'); data.value = response.data; }; return { data, getData, }; }, }); </script> ``` 在上面的示例中,我们首先创建了一个`Api`类,它封装Axios的所有HTTP请求方法,并添加了请求和响应拦截器。然后,在Vue组件中引入该类并调用其方法来发起HTTP请求,最后将响应数据绑定到组件的数据属性中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值