axios 类的二次封装

615 阅读3分钟

前言

大家好,我是个工作了几年了几年,编程水平依旧稀烂的前端,如有错误,请大佬们来指点一二,写文章只是为了养成好的习惯,早日像众多大佬靠拢

最终想实现的效果,通过实例化类,发送网络请求

const http = new GRequest({
    baseURL: 'http://localhost:8080/',
    timeout: 10000,
    interceptors:{}
})
http.request({
  url: '/get/tableinfo',
  method: 'GET',
  headers: {},
  interceptors: {
    requestInterceptor: (config) => {
      console.log('单独请求的config')
      config.headers['token'] = '123'
      return config
    },
    responseInterceptor: (res) => {
      console.log('单独响应的response')
      return res
    }
  }
})

1. 封装一个GRequest类,通过实例化这个类发送get 请求

import axios from 'axios'
class GRequest {
    constructor(config){
        //实例化axios 对象
        this.instance = axios.create(config)
    }
    request(config){
        this.instance.request(config).then(res => {
            console.log(res)
        })
    }
}

const http = new GRequest({baseURL:'地址'timeout:10000})
http.request({
    url:'',
    method:'Get'
})
//这里已经能正常发送请求了

2. 现在开始封装拦截器interceptors,我们可以在实例化对象时传递给GRequest,让拦截器更加动态,这样当出现多种不同的业务,需要不同的拦截时,书写不同的方法,不必用if else不停累加

new GRequest({
    baseURL:'地址'timeout:10000, 
    //这是传入的拦截器 interceptors  
    interceptors: {
    requestInterceptor: (config) => {
      console.log('请求成功的拦截')
      return config
    },
    requestInterceptorCatch: (err) => {
      console.log('请求失败的拦截')
      return err
    },
    responseInterceptor: (res) => {
      console.log('响应成功的拦截')
      return res
    },
    responseInterceptorCatch: (err) => {
      console.log('响应失败的拦截')
      return err
    }})
class GRequest {
  instance
  interceptors
  constructor(config) {
     //实例化axios对象
    this.instance = axios.create(config)
    保存拦截器
    this.interceptors = config.interceptors
    //取出传入的拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )
  }
   request(config){
        this.instance.request(config).then(res => {
            console.log(res)
        })
    }
   

}

3 添加所有实例公共的拦截器,上一步封装的拦截器是实例化对象的

constructor(config){
   this.instance = axios.create(config)
   this.interceptors = config.interceptors
    this.instance.interceptors.request.use(config => {
     console.log('所有的实例都有的拦截器: 响应成功拦截')
      return config
    }, err => {
    console.log('所有的实例都有的拦截器: 请求失败拦截')
      return err
    })
    this.instance.interceptors.response.use(res => {
      const data = res.data
      //根据状态码做特殊处理
      if (data.returnCode === '-1001') {
        console.log('所有的实例都有的拦截器: 响应成功拦截')
      } else {
        return data
      }
    }, err => {
        console.log('所有的实例都有的拦截器: 响应失败拦截')
      return err
    })
}

  1. 对单个请求的拦截 当想对某些特殊的接口进行单独拦截时如下
http.request({
  url: '/table/userlist',
  method: 'GET',
  interceptors: {
    requestInterceptor: (config) => {
      console.log('单独请求的config')
      return config
    },
    responseInterceptor: (res) => {
      console.log('单独响应的response')
      return res
    }
  }
})

request(config){
      //由于要进行单独拦截,原本定义的拦截器就不再使用
    if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config)
     }
   this.instance.request(config).then(res => {
        if (config.interceptors?.responseInterceptor) {
          res = config.interceptors.responseInterceptor(res)
        }
     }).catch( err => { return err })

5. 拿到请求成功的结果 直接将request的内容 用promise 封装,return一个promise对象

request(config){
 return new Promise((resolve, reject) => {
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config)
      }
      this.instance.request(config).then(res => {
        if (config.interceptors?.responseInterceptor) {
          res = config.interceptors.responseInterceptor(res)
        }
        resolve(res)
      }).catch(err => {
        reject(err)
        return err
      })
    })
}
http.request({
    url:'./',
    method:'GET'
}).then(res => {
    console.log('拿到请求结果')
})

6. 封装request之外的其他请求 get,post,delete 等在class 类里添加其他方法

 get(config) {
    return this.request({ ...config, metho: 'GET' })
  }
  post(config) {
    return this.request({ ...config, metho: 'POST' })
  }
  delete(config) {
    return this.request({ ...config, metho: 'DELETE' })
  }

完整的GRequest类

class GRequest {
  constructor(config) {
    this.instance = axios.create(config)
    this.interceptors = config.interceptors

    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )

    this.instance.interceptors.request.use(config => {
      return config
    }, err => {
      return err
    })

    this.instance.interceptors.response.use(res => {
      const data = res.data
      if (data.returnCode === '-1001') {
        console.log('请求失败~, 错误信息')
      } else {
        return data
      }
    }, err => {
      return err
    })
  }
  request(config) {
    return new Promise((resolve, reject) => {
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config)
      }
      this.instance.request(config).then(res => {
        if (config.interceptors?.responseInterceptor) {
          res = config.interceptors.responseInterceptor(res)
        }
        resolve(res)
      }).catch(err => {
        reject(err)
        return err
      })
    })
  }
  get(config) {
    return this.request({ ...config, metho: 'GET' })
  }
  post(config) {
    return this.request({ ...config, metho: 'POST' })
  }
  delete(config) {
    return this.request({ ...config, metho: 'DELETE' })
  }
  patch(config) {
    return this.request({ ...config, metho: 'PATCH' })
  }
}