zoukankan      html  css  js  c++  java
  • vue+axois 封装请求+拦截器(请求锁+统一处理错误码)

     需求

    1.  封装常用请求
    2.  拦截器-请求锁
    3.  统一处理错误码

    一、封装常用的请求

      解决痛点:不要每一个模块的api都还要写get,post,patch请求方法。直接将这些常用的方法封装好。

      解决方案:写一个类,封装好常用的请求

      部分源码如下

    export default class PublicAPI {
        constructor(url) {
            this.url = url;
        }
    
        get(params, filter) {
            if (Array.isArray(params)) {
                filter = typeof filter === 'object' ? JSON.stringify(filter) : filter;
                let qs = filter ? '?filter=' + filter : '';
                return axios.get(this.url + '/' + params.join('/') + qs);
            }
            params = params || {};
            return axios.get(this.url, { params });
        }
    
        delete(id) {
            return axios.delete(`${this.url}/${id}`);
        }
    
        post(params) {
            return axios.post(this.url, params);
        }
       //常用请求 都可以封装在这里 }

    二、拦截器-请求锁

      解决痛点:限制同一时间发多个同一个请求

      解决方案:利用axios的拦截器 + axios.CancelToken,限制同一个请求多次发送

      源码如下

    方案一:简单款

    let pending = []; //声明一个数组用于存储每个ajax请求的取消函数和ajax标识
    let CancelToken = axios.CancelToken;
    let removePending = (config) => {
        for(let p in pending){
            if(pending[p].u === config.url + '&' + config.method) { //当前请求在数组中存在时执行函数体
                pending[p].f(); //执行取消操作
                pending.splice(p, 1); //把这条记录从数组中移除
            }
        }
    }

    方案二:复杂款(这个是在掘金上看到的,原链接找不到了)

    let pending = {};
    /**
     * cancelKey管理器
     *
     * @return {Object} 返回一个对象,对象暴露两个方法,一个可以获取本次请求的key,一个是设置本次请求的key
     * @memberof HttpRequest
     */
    let cancelKeyManager = () => {
        const expose = {};
        expose.setKey = function setKey(config) {
            const { method, url, params, data } = config;
            expose.key = `${method}|${url}`;
            //expose.key = method === 'get' ? `${expose.key}&${JSON.stringify(params)}` : `${expose.key}&${JSON.stringify(data||{})}`;
        };
        expose.getKey = function getKey() {
            return expose.key;
        };
        return expose;
    };
    
    /**
     *处理请求拦截和请求取消
     *
     * @param {object} config axios配置对象
     * @param {boolean} [isCancel=true] 标识是请求取消还是拦截请求
     * @return {object} 返回axios配置对象
     * @memberof HttpRequest
     */
    let handleRequestCancel = (config, isCancel = false) => {
        // 设置本次请求的key
        const { setKey, getKey } = cancelKeyManager();
        setKey(config);
        const key = getKey();
        const CancelToken = axios.CancelToken;
        // 取消已经发出去的请求
        if (isCancel) {
            removeRequest(key, true);
            // 设置本次请求的cancelToken
            config.cancelToken = new CancelToken(c => {
                pending[key] = c;
            });
        } else {
            // 拦截本次请求
            config.cancelToken = new CancelToken(c => {
                // 将本次的cancel函数传进去
                pending[key] = c;
                removeRequest(key, true, c);
            });
        }
    
        return config;
    };
    
    /**
     * 移除请求
     *
     * @param {string} key 标识请求的key
     * @param {boolean} [isRequest=false] 标识当前函数在请求拦截器调用还是响应拦截器调用
     * @param {function} c cancel函数
     * @memberof HttpRequest
     */
    let removeRequest = (key, isRequest = false, c) =>{
        // 请求前先判断当前请求是否在pending中,如果存在有两种情况:
        // 1. 上次请求还未响应,本次的请求被判为重复请求,则调用cancel方法拦截本次重复请求或者取消上一个请求
        // 2. 上次请求已经响应,在response中被调用,清除key
        console.log(key,pending);
        if (pending[key]) {
            if (isRequest) {
                Message.error({
                    message: '请求过于频繁'
                });
            } else {
                // 上一次请求在成功响应后调用cancel函数删除key
                delete pending[key];
            }
        }
    };

    三、统一处理错误码

      解决痛点:每个请求都需要处理错误信息,特别是一些常用的错误(坚持能封装就封装的思想),当然具体业务处理逻辑这是各自处理啦!

      解决方案:用axios拦截器,将返回来的错误统一处理,最常用的就是401 token失效吧!一般是要前后端统一错误码的,固定的错误码做固定的事情!

      部分源码如下(感觉只适合部分)

    axios.interceptors.response.use(
    response => {
    return new Promise((resolve, reject) => { //很重要 用promise 接收自定义错误码
    let data = response.data;
    if (data.code === 'ok') {
    return resolve({
    data: data.data || data || {},
    response: response
    });
    } else {
    switch (data.code) {
    case '10500': //自定义code
    reject({
    response: {
    code: '10500',
    status: 500,
    msg: data.msg
    }
    });
    break;
    default:
    reject(response);
    }
    }
    });
    },error => {}
    )

    总结

      给出的源码比较分散,仅提供思路。

      在项目中这么一套全家桶用下来,十分巴适~~~

      有疑问可以给我留言,我会尽力解答哦

  • 相关阅读:
    算法|LeetCode之找零钱[Java]
    算法|LeetCode之最大子段和[Java]
    算法|LeetCode之打家劫舍[Java]
    设计模式|观察者模式
    设计模式|原则—依赖倒置原则
    设计模式|原则—开闭原则
    数据库|MyBatis项目配置案例详解与Web下的增删改查实现[附项目源码]
    数据库|深入浅出MYSQL数据库—思维导图[附下载链接]
    算法|深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现
    Java|单向链表的实现
  • 原文地址:https://www.cnblogs.com/ifannie/p/13955395.html
Copyright © 2011-2022 走看看