Vue Axios请求封装

Vue Axios请求封装

第一步:配置axios

首先,创建一个tools.js,这里面存放的是接口配置、请求出错和当前环境配置,我平常elementUI用的比较多,这里你也可以使用自己的UI库。

import {
    Message
} from 'element-ui';
//判断当前环境
let env = window.location.href.includes('test') ? "test" :
    (window.location.href.includes('me-web-test') || window.location.href.includes('localhost')
        || window.location.href.includes('192.168') || window.location.href.includes('127.0.0.1')) ? "develop" : "production";

const Conts = {
    env,
    domain: (env === 'develop') ? `测试接口1` : (env === 'test') ? `测试接口2` : `生产接口`,
    popupTime: 1000,
    popupTimes: [500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000],
};
/**
 * @description 通用提示
 */
const Alert = {
    //fetch 错误提示
    permissionError(option) {
        let _status = option.data.status || option.data.response.status;
        let _mes = option.data.response.data.message;
        if (_status === 400) {
            let newMes = '';
            if (Object.keys(option.data.response.data.data).length !== 0) {
                for (let item in option.data.response.data.data) {
                    if (newMes !== '') {
                        newMes += `;${option.data.response.data.data[item]}`;
                    } else {
                        newMes += `${option.data.response.data.data[item]}`;
                    }
                }
            }
            _mes = newMes ? newMes : _mes ? _mes : '参数错误,请稍后重试。';
            option.cb = (typeof option.cb === 'function') ? option.cb : function () {};
            if (option.popup) {
                Message({
                    message: _mes,
                    type: 'error',
                    duration: Conts.popupTimes[6],
                }).then(() => {
                    option.cb();
                });
            } else {
                option.cb();
            }
        } else if (_status === 401) {
            if (option.cb) {
                option.cb();
            }
        } else if (_status === 403) {
            _mes = _mes ? _mes : '您没有权限';
            option.cb = (typeof option.cb === 'function') ? option.cb : function () {};
            option.popup = (typeof option.popup === 'boolean') ? option.popup : true;
            if (option.popup) {
                Message({
                    message: _mes,
                    type: 'error',
                    duration: Conts.popupTimes[6],
                }).then(() => {
                    option.cb();
                });
            } else {
                option.cb();
            }
        } else if (_status === 429) {
            _mes = _mes ? _mes : '您尝试太多次啦,请稍后再试。';
            option.cb = (typeof option.cb === 'function') ? option.cb : function () {};
            option.popup = (typeof option.popup === 'boolean') ? option.popup : true;
            if (option.popup) {
                Message({
                    text: _mes,
                    type: 'error',
                    duration: Conts.popupTimes[6],
                }).then(() => {
                    option.cb();
                });
            } else {
                option.cb();
            }
        } else if (_status === 404) {
            _mes = _mes ? _mes : '页面丢失';
            option.cb = (typeof option.cb === 'function') ? option.cb : function () {};
            option.popup = (typeof option.popup === 'boolean') ? option.popup : true;
            if (option.popup) {
                Message({
                    message: _mes,
                    type: 'error',
                    duration: Conts.popupTimes[6],
                }).then(() => {
                    option.cb();
                });
            } else {
                option.cb();
            }
        } else {
            console.warn(`其他错误码:${_status}`)
        }
    },
};


export default {
    Conts,
    Alert
}

第二步:引用tools.js

在main.js中全局引用以及axios配置拦截器等

import Vue from 'vue'
import axios from 'axios'
import tools from './js/vuex/tools' // 全局定义接口变量
Vue.prototype.$axios = axios
Vue.prototype.$Tools = tools

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
  // 对响应数据做点什么

  if (response.data.message == "您没有获得授权") {
    Message({
      type: 'warning',
      message: '您没有获得授权,请重新登录'
    });
    router.push({
      name: "loginnew"
    })
  }
  return response;
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error);
});

第三步:使用

在需要的页面进行接口请求

//account:请求的接口
//params:参数
       this.$axios
            .post(`${this.$Tools.Conts.domain}account`, params)
            .then(res => {
            //请求成功
              if (res.data) {
                if (res.data.code === 0) {
                  this.$message({
                    type: "success",
                    message: res.data.message
                  });
                } else {
                  this.$message({
                    type: "warning",
                    message: res.data.message
                  });
                }
              }
            })
            .catch(err => {
            //请求失败
              this.$Tools.Alert.permissionError({
                data: err,
                popup: true
              });
            });   

axios 防止重复请求

在我们进行数据请求时,在上一个请求还未响应完成时,我们又发送了重复的请求,这样会造成资源损耗、性能下降,针对这样的问题,我们可以全局配置如下 axios 请求

import axios from "axios";

/**
 * @description 函数返回唯一的请求key **/
function getRequestKey(config) {
    let {
        method,
        url,
        params,
        data
    } = config;
    return [method, url, JSON.stringify(params), JSON.stringify(data)].join("&");
}

/**
 * @description 添加请求信息 **/
let pendingRequest = new Map();

function addPendingRequest(config) {
    let requestKey = getRequestKey(config);
    config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
        if (!pendingRequest.has(requestKey)) {
            pendingRequest.set(requestKey, cancel);
        }
    });
}

/**
 * @description 取消重复请求,移除重复请求信息 **/
function removePendingRequest(config) {
    let requestKey = getRequestKey(config);
    if (pendingRequest.has(requestKey)) {
        // 重复请求时调用该函数
        let cancel = pendingRequest.get(requestKey);
        cancel(requestKey);
        // 删除上一次接口请求
        pendingRequest.delete(requestKey);
    }
}

/**
 * @description 请求拦截器 **/
axios.interceptors.request.use(
    function (config) {
        // 取消重复请求,移除重复请求信息
        removePendingRequest(config);
        // 把当前请求信息添加到pendingRequest对象中
        addPendingRequest(config);
        return config;
    },
    function (error) {
        return Promise.reject(error);
    }
);

/**
 * @description 响应拦截器**/
axios.interceptors.response.use(
    function (response) {
        removePendingRequest(response.config);
        return response;
    },
    function (error) {
        removePendingRequest(error.config || {});
        if (axios.isCancel(error)) {
            //取消重复请求
            console.log(error.message);
        } else {
            console.log('异常处理')
        }
        return Promise.reject(error);
    }
);

export default axios

 

posted @ 2022-01-24 14:18  Mr▪小zhou  阅读(102)  评论(0编辑  收藏  举报