axios的二次封装与async,await的配合使用?

前言:前些日子读文章,说是vue3.0会在明年下半年正式推出,改动的地方好像也不少,比如说vue3.x的代码库将会用typescript编写,并提供改进的 TypeScript 支持.变化还是很快的,虽然水平还差的远,可路还是一步一步走吧.ok,回到正题,在vue2.x的版本中请求数据推荐使用的axios,之前我常常使用的axios的别名方法,比如说在vue组件中:

axios.get('http://localhost:3000/user')
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err)
    })
复制代码

如果一个页面发多个请求,那写法上还是比较麻烦的,并没有async,await的写法清爽,也没有体现出所谓面向对象编程啊,es6中类的思想和优势.所以文章分三部分,一部分是axios的二次封装,另一部分是async,await的使用,再一部分是对别人的借鉴!

axios的二次封装

以vue2.x的webpack为例说明

src文件夹结构目录

基础原理

使用axios去自定义创建实例,挂载请求所需配置项

axios.create([config])

//抄来的案例
const instance = axios.create({
    baseURL: 'http://exemple.com/api/',
    timeout: 1000,
    header: {'X-Custom-Header': 'foobar'}
})
复制代码

axios的github地址

文件说明

config文件夹下的url.js文件
// axios请求的默认请求地址,区分生产环境与开发环境
// 题外话,vue2.x项目中会有服务器代理的配置项(上篇文章有提及)
// 此处的的axios的默认地址会拼接在代理配置项的基地址之后
// 所以呢,结合实际情况设置axios的默认请求地址
export const baseURL = process.env.NODE_ENV === 'production'
  ? '/production'
  : '/development'

复制代码
libs文件夹下的axios.js文件
import axios from 'axios'
import {baseURL} from '@/config/url'
// 主要是在处理put,post等请求的传参情况
// 有时后端会需要将传递的对象参数转化成urlcode的形式
// qs就能发挥相应的作用
import qs from 'qs'

// es6当中类的一个写法,面向对象思想的一个体现
// 不明白自行查资料哦
class HttpRequest {
  constructor (baseUrl = baseURL) {
    this.baseUrl = baseUrl
  }
  
// 设置axios的请求实例的默认配置项
  getInsideConfig () {
    const config = {
      baseUrl: this.baseUrl,
      headers: {
        //
      }
    }
    return config
  }

// axios的拦截器
  interceptors (instance) {
  
    // 请求拦截器(比如在此处验证一下是否有发请求的权限)
    instance.interceptors.request.use(config => {
      return config
    }, error => {
      return Promise.reject(error)
    })
    
    // 响应拦截器
    // (比如对返回的参数做一些处理,比如请求状态的提示语的处理)
    // (拿data中的数据,response对象可能是有很多层data的)
    instance.interceptors.response.use(res => {
      return res
    }, err => {
      return Promise.reject(err)
    })
  }

// 此处即为创建请求实例,真正在请求中发挥作用的地方
  create (options) {
    if (options.method === 'post' || options.method === 'put') {
      options.headers['Content-Type'] = 'application/x-www-form-urlencoded'
      
      // post,put请求需要将传递的数据挂载在data项上
      // 后台需要传递参数urlcode化/参数序列化时,使用qs
      options.data = qs.stringify(options.data)
    } else {
    
      // get等请求的数据挂在params项上,当然params项上也可以挂post等请求的参数,
      // 但是不严谨,且参数拼接到地址栏上也不安全,有长度限制
      options.params = options.data
    }
    return axios.create(options)
  }

// 暴露到其他文件中被使用的方法,options参数也是外部文件传递进来的
  request (options) {
  
  // Object.assign返回一个将参数对象的属性合并后的一个对象
    options = Object.assign(this.getInsideConfig(), options)

    const instance = this.create(options)

    this.interceptors(instance)

    return instance(options)
  }
}

export default HttpRequest

复制代码
libs文件夹下axiosRequest.js文件
// 实际上本文件只是起了一个中转作用,一个类的实现或者叫实例化
import HttpRequest from '@/libs/axios'

const axios = new HttpRequest()

export default axios

复制代码
api文件夹下order.js文件
// system.js是系统设置模块的一些请求方法
// 订单模块,请求方法的集中处理
import axios from '@/libs/axiosRequest'

// 获取订单列表(刷新页面时,进入的是未处理订单)
export const getOrderList = (getData) => {
  const data = {
    page: getData.page,
    rows: getData.rows,
    orderStatus: getData.orderStatus,
    keyWord: getData.keyWord
  }
  return axios.request({
    url: '/carscraporder-manager/order',
    data,
    method: 'get'
  })
}
// 获取订单详情
export const getOrderDetail = (id) => {
  return axios.request({
    url: `/carscraporder-manager/order/${id}`,
    method: 'get'
  })
}
// 旧件订单派单异常
export const abnormalPartOrder = (id, data) => {
  return axios.request({
    url: `/carscraporder-manager/order/audit/${id}`,
    data,
    method: 'put'
  })
}
复制代码

async,await的使用

views文件夹下Order.vue文件
// 按需引入请求方法
<script>
import { getOrderList, getHistoryOrderList, getAllOrderList, getOrderDetail } from '@/api/order'
export default {
    data() {
        return {
          // 判定当前所要查询的订单状态,默认1为未处理,2为已处理,3为全部
          orderState: 1,
          // 要传递给旧件编辑页面的表单数据
          partOrderDetail: {},
          // 要传递给整车编辑页面的表单数据
          newOrderdetail: {},
          tableData: [],
          query: '',
          pagenum: 1,
          total: 0,
          // 旧件编辑页面开关变量
          partEditvisible: false,
          // 整车编辑页面开关变量
          allEditvisible: false,
          options: [],
          currentRoleId: -1
        }
    },
    methods: {
    // 全部订单
    async allOrderList () {
      this.pagenum = 1
      this.orderState = 3
      let data = {
        page: 1,
        rows: 10
      }
      const response = await getAllOrderList(data)
      if (response.data.code === 200) {
        this.tableData = response.data.data.rows
        this.total = response.data.data.total
      } else {
        this.$message.error('全部订单列表获取失败')
      }
    },
    }
}
</script>
复制代码

别人的一些观点和优化

  • 响应拦截时错误http状态码的处理

引用详情

//axios捕错,需要引入的一个文件
export const throwErr = (code, response) => {
  let message = '请求错误'
  switch (code) {
    case 400:
      message = '请求错误'
      break
    case 401:
      message = '未授权,请登录'
      break
    case 403:
      message = '拒绝访问'
      break
    case 404:
      message = `请求地址出错: ${response.config.url}`
      break
    case 408:
      message = '请求超时'
      break
    case 500:
      message = '服务器内部错误'
      break
    case 501:
      message = '服务未实现'
      break
    case 502:
      message = '网关错误'
      break
    case 503:
      message = '服务不可用'
      break
    case 504:
      message = '网关超时'
      break
    case 505:
      message = 'HTTP版本不受支持'
      break
    default:
  }
  return message
}

复制代码
  • 响应之后销毁请求实例
class httpRequest {
  constructor () {
    // 存储请求队列
    this.queue = {};
  }
  
 // 销毁请求实例
  destroy (url) {
    delete this.queue[url];
    
    // Object.keys:属性名字符串组成的一个数组
    const queue = Object.keys(this.queue);
    return queue.length;
  }  
  
  interceptors (instance, url) {
    instance.interceptors.response.use((res) => {
      let { data } = res;
      this.destroy(url);
    }
  }
  // 请求实例
  request (options) {
    var instance = this.create(options);
    // url为属性名,instance为属性值
    this.queue[options.url] = instance;
  }
复制代码
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值