一、概述
对 Axios
进行简单封装。
二、目标
1、异常处理
对于将网络错误、HTTP 错误和返回值错误合并,方便上层处理。
服务端返回的数据至少包含 code
和 message
字段。code
是 200
时为正常返回。
2、支持跳转 URL
服务端返回的数据如果包含 url
字段,则自动跳转至对应地址。
如果包含 url
字段,不会对 code
进行判断。
3、JSON 序列化
对于 post
、put
和 patch
方法提交的数据,序列化成 JSON 。
4、QueryString 序列化
对于 get
、delete
和 head
方法提交的数据,序列化成 QueryString 。
5、同时支持 JOSN 和 文件下载
服务器可能返回不同的数据格式,比如返回文件或 JSON
格式————当文件由于某些原因不可下载时返回 JSON
格式。
6、封装 Vue plugin
将 Axios
的实例封装成一个 plugin ,方便 Vue.use(xxxx) 。
三、实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| import axios from 'axios' import qs from 'qs' import { baseURL } from './config.js'
const SuccessCode = 200
const ErrorType = { 'Default': 'default', 'Sysetem': 'sysetem' }
function ApiError (message, errorType, innerError) { this.name = 'ApiError' this.message = message || 'Default Message' this.errorType = errorType || ErrorType.Default this.innerError = innerError this.stack = (new Error()).stack } ApiError.prototype = Object.create(Error.prototype) ApiError.prototype.constructor = ApiError
const httpClient = axios.create({ baseURL: baseURL, timeout: 20000, responseType: 'json', withCredentials: true })
httpClient.interceptors.request.use( config => { if ( config.method === 'post' || config.method === 'put' || config.method === 'patch' ) { config.headers = { 'Content-Type': 'application/json; charset=UTF-8' } config.data = JSON.stringify(config.data) } else if ( config.method === 'delete' || config.method === 'get' || config.method === 'head' ) { config.paramsSerializer = function (params) { return qs.stringify(params, { arrayFormat: 'indices' }) } }
if (localStorage.token) { config.headers.Authorization = localStorage.token } return config }, error => { return error } )
httpClient.interceptors.response.use( response => { if (response.headers['content-type'].indexOf('json') === -1) { return response } let json if (response.request.responseType === 'arraybuffer' && response.data.toString() === '[object ArrayBuffer]') { const text = Buffer.from(response.data).toString('utf8') console.log(text) json = JSON.parse(text) } else { json = response.data }
if (json && json.url) { top.location = json.url } else if (json && json.code !== SuccessCode) { console.log(json) return Promise.reject(new ApiError(json.message)) } return response }, error => { return Promise.reject(new ApiError(error.message, ErrorType.Sysetem, error)) } )
export default { install: function (Vue, option = {}) { Vue.httpClient = httpClient Vue.prototype.$httpClient = httpClient } }
|
config.js 内容:
1
| export const baseURL = 'http://www.yourdomain.com/api'
|
四、使用
1、Vue 配置
1 2 3 4 5 6 7 8
| import Vue from 'vue' import HttpClient from '@/utils/httpclient.js'
import App from './App.vue'
Vue.use(HttpClient)
|
2、示例
1 2 3 4 5 6 7 8 9 10 11 12 13
| login () { const params = { username: 'test', password: '123456' } Vue.httpClient.post('/login', params).then(response => { console.log(response.data) }, error => { console.log(error) }) }
|
3、下载支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const fileDownload = require('js-file-download')
testDownload () { const url = 'http://www.yourdomain.com/somefile.zip' const params = { token: '35dea0e5-9b9f-4b8b-981e-2e1120b1c317' } Vue.httpClient.post(url, params, { responseType: 'arraybuffer' }).then(response => { fileDownload(response.data, 'somefile.zip') }, error => { console.log(error) }) }
|
参考资料