React axios二次封装

这篇博客介绍了如何结合axios的请求和响应拦截器,以及antd的Spin和Message组件,来实现在API请求期间显示loading效果和错误消息提示。默认情况下,每个请求都将显示loading,但可以通过在请求headers中设置isLoading为false来关闭此功能。同时,文章展示了创建和销毁loading元素的逻辑,以及如何处理请求和响应数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 通过 axios 提供的请求拦截和响应拦截的接口,控制 loading 的显示或者隐藏。
  2. 采用antd的Spin组件来实现loading效果,message组件来进行消息提示。
  3. 默认所有请求都会自动有 loading 效果。如果某个请求不需要 loading 效果,可以在请求 headers 中设置 isLoading 为false。
import axios from "axios";
import _isEmpty from "lodash/isEmpty";
import _omitBy from "lodash/omitBy";
import { getTimestamp } from "./utils";
import { message, Spin } from 'antd';

const { protocol } = window.location; // 协议
const { host } = window.location; // 主机

// 显示loading
const createLoading = () => {
    let loadingWrapper = document.createElement("div");
    loadingWrapper.setAttribute("id", "loading");
    document.body.appendChild(loadingWrapper);
    const SpinHtml = <Spin size="lg"  spinning />;
    render(React.cloneElement(SpinHtml), loadingWrapper);
    return {
    	// 隐藏loading
        hide() {
            document.body.removeChild(loadingWrapper);
            loadingWrapper = null;
        },
    };
};
// 区分环境
if (process.env.NODE_ENV === "development") {
    // 若本地项目调试使用
    axios.defaults.baseURL = `${protocol}//${host}/api`;
} else {
    // 动态请求地址             协议               主机
    axios.defaults.baseURL = `${protocol}//${host}`;
}

axios.defaults.timeout = 100000;
axios.defaults.withCredentials = true;
axios.defaults.headers["Content-Type"] = "application/json;charset=UTF-8";
axios.interceptors.request.use(
    (config) => {
        const ts = getTimestamp();

        config.headers = {
            "X-Requested-With": "XMLHttpRequest",
            "Cache-Control": "no-cache",
            Pragma: "no-cache",
            ts,
            ...config.headers,
        };
        // if (Object.prototype.toString.call(config.data) !== '[object FormData]') {
        //     config.data = qs.stringify(config.data);
        // }
        return config;
    },
    (error) => Promise.reject(error)
);

axios.interceptors.response.use(
    (response) => {
        return response;
    },
    // 服务器状态码不是200的情况
    (error) => {
        return Promise.reject(error);
    }
);

function filterParams(params) {
    return _omitBy(params, (param) => {
        const type = typeof param;
        if (type === "number" || type === "boolean") {
            return false;
        }
        if (type === "string") {
            return param.trim() === "";
        }
        return _isEmpty(param);
    });
}

export function request(config, showLoading = true) {
    const { url, method, data, params, header } = config;

    function createLoadingWrapper() {
        if (showLoading) {
            return createLoading();
        }
        return null;
    }

    let _loading = createLoadingWrapper();

    function hideLoading() {
        if (_loading) {
            _loading.hide();
            _loading = null;
        }
    }

    return new Promise((resolve, reject) => {
        let _params = null;
        let _data = null;
        if (method === "GET") {
            _params = filterParams(params || data);
        } else {
            _data = data;
            _params = filterParams(params);
        }
        axios({
            method,
            url,
            data: _data,
            params: _params,
            headers: header,
        })
            .then((res) => {
                if (!res) {
                    return;
                }
                if (res.data.code === 200) {
                    resolve(res.data);
                } else {
                    reject(res.data);
                }
                hideLoading();
            })
            .catch((error) => {
                // eslint-disable-next-line prefer-promise-reject-errors
                reject({
                    message: error.msg,
                    code: error.code,
                    ...error.data,
                });
                hideLoading();
            });
    });
}

公共样式文件添加css

#loading {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    font-size: 20px;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值