axios的二次封裝與async,await的配合使用?

前言:前些日子讀文章,說是vue3.0會在明年下半年正式推出,改動的地方好像也很多,好比說vue3.x的代碼庫將會用typescript編寫,並提供改進的 TypeScript 支持.變化仍是很快的,雖然水平還差的遠,可路仍是一步一步走吧.ok,回到正題,在vue2.x的版本中請求數據推薦使用的axios,以前我經常使用的axios的別名方法,好比說在vue組件中:vue

axios.get('http://localhost:3000/user')
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err)
    })
複製代碼

若是一個頁面發多個請求,那寫法上仍是比較麻煩的,並無async,await的寫法清爽,也沒有體現出所謂面向對象編程啊,es6中類的思想和優點.因此文章分三部分,一部分是axios的二次封裝,另外一部分是async,await的使用,再一部分是對別人的借鑑! webpack

axios的二次封裝

以vue2.x的webpack爲例說明ios

src文件夾結構目錄

基礎原理

使用axios去自定義建立實例,掛載請求所需配置項git

axios.create([config])es6

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

axios的github地址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狀態碼的處理

引用詳情web

//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;
  }
複製代碼
相關文章
相關標籤/搜索