哥伦布

Axios请求响应拦截器统一封装

复制代码
/*
 * @Description: 
 * @Author: NanKe
 * @Date: 
 * @LastEditTime: 
 * @LastEditors: NanKe
 * @Cnblogs: https://www.cnblogs.com/NanKe-Studying/
 * @FilePath: \cloud-teach-aide\web\src\http.js
 */
import axios from 'axios'
import vueMain from './main'

const defaultConfig = {
    baseURL: process.env.VUE_APP_BASEURL,
    timeout: 30 * 1000, //超时时间,下面设置了超时重连机制
    //如果设置超时时间太小,会报timeout of xxxms exceeded
    //是因为请求+返回时间超过了设置的超时时间,比如网络不好或后台接口数据太过于庞大
    retry: 2, //请求次数
    retryDelay: 1000, //请求间隙
    headers: {
        'Content-Type': 'application/json; charset=utf-8'
    }
}

const instance = axios.create(defaultConfig)

let loadingComponent
instance.interceptors.request.use(req => {
    loadingComponent = vueMain.$buefy.loading.open();
    // 1.比如req中的一些信息不符合服务器的要求,这里可以做一些修改
    // 2.比如每次发送网络请求时,都希望在界面中显示一个请求的图标(然后再响应拦截中取消显示)
    // 3.某些网络请求必须携带一些特殊的信息(如登录token),如果没有携带就可以拦截并作响应提示
    // 4.某些请求要求用户必须登录, 判断用户是否有token, 如果没有token跳转到login页面
    // 5.对请求的参数进行序列化(看服务器是否需要序列化) req.data = qs.stringify(req.data)
    return req
}, err => {
    // 请求未成功发出,如:没有网络...
    return Promise.reject(err)
})

instance.interceptors.response.use(res => {
    setTimeout(() => {
        loadingComponent.close();
        //下面是判断后端是调用了success还是fail响应给前端
        let { code, message } = res.data
        switch (code) {
            case -1:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-danger',
                    message
                })
                break;
            case 0:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-black',
                    message
                })
                break;
            case 200:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-success',
                    message
                })
                break;

        }
    }, 0.2 * 1000);

    // 成功响应的拦截
    return Promise.resolve(res.data)
}, err => {
    if (err.response) {
        // 失败响应的status需要在response中获得
        switch (err.response.status) {
            case 400:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-danger',
                    message: "请求无效,请求未到达服务端"
                })
                break;
            case 401:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-danger',
                    message: "未授权的访问"
                })
                vueMain.$router.push('/')
                break
            case 403:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-danger',
                    message: "禁止访问"
                })
                break;
            case 404:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-danger',
                    message: "页面不存在"
                })
                vueMain.$router.push('/')
                break
            case 405:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-danger',
                    message: "不支持的方法"
                })
                break
            default:
                vueMain.$buefy.toast.open({
                    duration: 2000,
                    type: 'is-danger',
                    message: "其他错误"
                })
                break
        }
    }

    // 请求超时,重新请求

    
    const { config, code, message } = err
    if (code === 'ECONNABORTED' || message === 'Network Error') {
        loadingComponent.close();
        vueMain.$buefy.toast.open({
            duration: 2000,
            type: 'is-danger',
            message: `请求超时,将在${defaultConfig.retryDelay / 1000}秒后重试`
        })
    }
    // 如果config不存在或未设置重试选项,请拒绝
    if (!config || !config.retry) return Promise.reject(err);

    // 设置变量跟踪重试次数
    config.__retryCount = config.__retryCount || 0;

    // 检查是否已经达到最大重试总次数
    if (config.__retryCount >= config.retry) {
        // 抛出错误信息
        return Promise.reject(err);
    }

    // 增加重试计数
    config.__retryCount += 1;
    // 创建新的异步请求
    var backoff = new Promise(function (resolve) {
        setTimeout(function () {
            resolve();
        }, config.retryDelay || 1);
    });

    // 返回axios信息,重新请求
    return backoff.then(function () {
        return axios(config);
    });

    // 注意这里应该return promise.reject(),因为如果直接return err则在调用此实例时,响应失败了也会进入then(res=>{})而不是reject或catch方法
    // return Promise.reject(err)
})


export default instance
复制代码

 

posted @   南柯Dream丶  阅读(835)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示