5.axios 封装请求,并实现接口防抖

303 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

封装了一个axios的请求方法,同时加了一个缓存防抖,以及请求错误时可以重新请求自动请求接口的方法. 当然,其中存在不完善的地方请见谅

  封装代码:

import axios from 'axios'
import qs from 'qs'

// 防抖数据
let requestDou =localStorage.getItem('requestDou')?JSON.parse(localStorage.getItem('requestDou')):[];

// 创建axios实例
const initAxios = (postData,timeout=60000) => {
    // 拦截
    const AxiosInstance = axios.create({
        baseURL: process.env.VUE_APP_BASE_URL,
        timeout: timeout,
        withCredentials: true,
        emulateJSON: true,
    }) 
    // 接口发起前
    AxiosInstance.interceptors.request.use(config => {
        config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
        // 不使用config里面的数据,如果做加解密判断,使用qs会改变数据的类型
        if(config.method.toUpperCase() === 'GET'){
            config.params=postData
        }else{
            config.data=qs.stringify(postData, { arrayFormat: 'indices'})
        }
        return config
    })
    // 接口发起后
    AxiosInstance.interceptors.response.use(
        // 成功的请求
        response => {
            if(response.data.status==1){
                return Promise.resolve(response.data)
            }else{
                return Promise.reject(response)
            }
        },
        // 失败的请求
        error=>{
            let errorMsgTitle=error || '请求失败!'
            let errorObjecy={
              msg:errorMsgTitle
            }
            // 页面超时
            if(error.code === 'ECONNABORTED' || error.message ==="Network Error" ||  error.message.includes("timeout")){  
              errorObjecy.msg='请求超时,请重新刷新页面'
              // 返回页面超时
              errorObjecy['isTimeout']=true
            }
            // 抛错
            return Promise.reject(errorObjecy)
        }
    )
    return AxiosInstance
}

// 防抖数据缓存处理
function setDouData(data,delIndex=0,number=0){
    if(number>0){
        requestDou.splice(delIndex,number)
    }else{
        requestDou.splice(delIndex,number,data)
    }
    localStorage.setItem('requestDou',JSON.stringify(requestDou))
}
// 清除防抖
function delDouData(data){
 setTimeout(()=>{
    let index=requestDou.findIndex(n=>n && n.url==data.url && data.data==n.data)
    if(index!=-1){
        setDouData(data,index,1)
    }
 },300)
}

// request方法
const requestAxios =(
    {
        url,
        method = 'post',
        data={},//参数
        timeout=60000,//超时时间,默认60秒
        is_anti=true,
    }
)=>{
    // axios配置
    const options = {
        url,
        method,
        params: method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE' ? data : null,
        data: method.toUpperCase() === 'POST' || method.toUpperCase() === 'PUT' ? data : null,
    }
    let thisPostTime=new Date().getTime()
    let requestDouItem={
        url:url,
        time:thisPostTime,
        data:JSON.stringify(data)
    }
    // 提交数据
    return new Promise((resolve, reject) => {
        // 接口防抖判断
        if(is_anti){
            if(requestDou.findIndex(n=>n && n.url==url && n.data==JSON.stringify(data))!=-1){
                reject({
                    msg:'操作频繁!'
                })
                return false;
            }
        }
        setDouData(requestDouItem)
        const AxiosInstance = initAxios(data,timeout)
        AxiosInstance(options).then(res=>{
            delDouData(requestDouItem)
            if(res){
                resolve(res)
            }
        }).catch(error=>{
            delDouData(requestDouItem)
            reject(error)
        })
    })

}
// 导出
export function request(requestParms,reuseData={}){
    if(!Object.hasOwnProperty.call(reuseData,'is_reuse')){
        reuseData.is_reuse=false
    }
    if(!Object.hasOwnProperty.call(reuseData,'num')){
        reuseData.num=1
    }
    return new Promise((resolve, reject) => {
        requestAxios(requestParms).then(res=>{
            resolve(res)
        }).catch(error=>{
            if(reuseData.is_reuse && reuseData.num>0){
                reuseData.num=reuseData.num-1
                request(requestParms,reuseData)
            }
            reject(error)
        })
    })
}

使用: 

import {request} from '@/utils/request'
request({
  url:'https://www.baidu.com',
  // method:'GET',
  data:{
    xx:99,
    c:88,
  }
},{is_reuse:true,num:5}).then(res=>{
  console.log(res)
})