React+ts+vite脚手架搭建(二)【接口篇】

523 阅读4分钟

前言

上一篇我们完成了前期准备和路由的封装:React+ts+vite脚手架搭建(一)【前期准备+路由篇】

本文我们将进行第二步:接口封装

image.png

众所周知,接口是一个项目中最重要的能力之一,一个好的接口封装,能让我们与后端的合作更加顺畅

下面我们将开始介绍如何封装一个接口:

具体步骤

下载依赖

相信很多人用的都是axios这个库吧,我们也是主要根据这个库进行封装

yarn add axios

封装一个http方法

我们将在这个方法中,进行请求拦截响应拦截登录态校验接口错误自动重试接口是否需要完整数据配置接口是否需要统一异常拦截 image.png

请求+响应拦截

我们这里创建了一个axios的实例,并在实例中注入接口请求的URL超时时间等配置,然后再拿出请求拦截+响应拦截,最后将实例通过一个方法给暴露出去

import axios from "axios";

// 取到对应的环境变量url
export const baseURL = import.meta.env.VITE_BASE_API;

// 创建一个axios实例
const request = axios.create({
    baseURL,
    timeout: 5000,
    withCredentials: true // 浏览器是否应该发送凭据(如 cookies、授权头等)到跨域请求的服务器
});

// 请求拦截器
request.interceptors.request.use((config) => {

    return config;
}, (error) => {
    return Promise.reject(error);
})

// 响应拦截器
request.interceptors.response.use((response) => {
    return response.data;
}, (error) => {
    return Promise.reject(error);
})

// 将方法封装成一个函数
const http = async (config: any): Promise<any> => {
    
    return request(config).then((res: IResponse) => {
        return res;
    }).catch(res => {
        return Promise.reject(res);
    });
}
export default http;

请求拦截token携带

在请求前,将token给放在请求头上,我这里是放在Authorization上,且这里可以采用自己想用的token存取方式

http.ts文件里修改:

......

 // 请求拦截器
request.interceptors.request.use((config) => {
    
    const token = getToken(); // 自定义获取token
    if (config?.headers && token) {
        config.headers["Authorization"] = token || "";
    }

    return config;
}, (error) => {
    return Promise.reject(error);
})

......

对未登录或者别的特殊的code进行统一处理

在我们正式的项目中,我们一般会跟后端统一规定一个个特殊的code,比如登录code为1000,权限code为1001等等,那么我们这里可以针对这些code进行统一的封装,这样,所有的接口都会统一走这个逻辑

我们这里先声明了一个枚举类型,方便统一管理特殊的code,然后呢,定义一个接口类型,最后在http方法里通过switch case的方式,去对不同的code进行特殊的逻辑处理


......
// 定义一个枚举code
enum ResCode {
    notLogin = 1001,
    notPower = 1002,
    // ... 其他状态码
}

// 定义一个接口类型
export interface IResponse<T = any> {
    code?: number;
    data?: T;
    msg?: string;
}

// 将方法封装成一个函数
const http = async (config: any): Promise<any> => {
    
    return request(config).then((res: IResponse) => {

        switch (res.code) {
            case ResCode.notLogin:
                // 未登录
                // window.location.href = '/login';
                break;
            case ResCode.notPower:
                // 无权限
                // window.location.href = '/403';
                break;
        }

        return res;
    }).catch(res => {
        return Promise.reject(res);
    });
}
......

对接口的数据+错误提示信息统一拦截

在我们日常的项目中,我们通常很多时候,不需要上述接口返回的code、data、msg等,只需要data即可,我们这里可以走一个配置,配置默认返回data;

以及对异常的code走一个统一的提示,因为在实际的项目中,我们不可能对每一个异常code都写一遍逻辑,首先,会有很多重复的工作量,其次,也可能会遗漏掉一些特殊的code的判断;

当然我们也要提前跟后端规定好,正确情况下的code值,比如0

// 自定义配置
interface IAxiosParam extends AxiosRequestConfig<any> {
    /**
     * 接口是否需要完整的res,默认不需要,直接返回res.data
     */
    needRes?: boolean;
    /**
     * 接口异常时是否进行统一拦截提示
     */
    noAlert?: boolean;
}

// 将方法封装成一个函数
const http = async (config: IAxiosParam): Promise<any> => {
    
    return request(config).then((res: IResponse) => {

        switch (res.code) {
            case ResCode.notLogin:
                // 未登录
                // window.location.href = '/login';
                break;
            case ResCode.notPower:
                // 无权限
                // window.location.href = '/403';
                break;
        }

        if (res.code !== 0 && !config.noAlert) {
            // 异常提示
            alert(res.msg || '出现问题啦~');
            return;
        }
        return config.needRes ? res : res.data;
    }).catch(res => {
        return Promise.reject(res);
    });
}

接口失败自动重试

这里我们使用个第三方依赖:axios-retry

yarn add axios-retry

然后直接用就行,还是比较简单的,通过axiosRetryaxios给包裹,并给出自动重试的次数

import axios, { AxiosRequestConfig } from "axios";

import axiosRetry from "axios-retry";

axiosRetry(axios, { retries: 3 });

重复接口拦截

这里可以详细看我这篇文章实战:针对慢网的一些实践与探索,保证不让你失望滴

使用

这里我们已经封装完毕,可以开始使用啦 我们在service的文件下写上代码:

image.png

踩踩坑

这里好像暂时没有碰到什么坑~

总结

本文主要介绍了如何封装脚手架的接口模块,包括防止重复请求、自动重试、接口拦截器等等等,较为简单实用,而且我在自己的实际demo中,也并没有遇到什么样的坑,欢迎大家尝试、建议!!!!

下一篇:React+ts+vite脚手架搭建(三)【状态管理篇】