注册

关于 Axios 的再再再封装,总是会有所不一样


特性


  • class 封装 可以多次实例化
  • 默认全局可以共用一个实例对象
  • 可以实例化多个对象,实例化时可以配置该实例特有的 headers
  • 根据各个接口的要求不同,也可以针对该接口进行配置
  • 设置请求拦截和响应拦截,这个都是标配了
  • 拦截处理系统响应状态码对应的提示语

拦截器


首先为防止多次执行响应拦截,这里我们将拦截器设置在类外部,如下:

import axios from "axios";

// 添加请求拦截器
axios.interceptors.request.use((config) => {
// 在发送请求之前做些什么 添加 token 等鉴权功能
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use((res) => {
const {status} = res;
// 对错误状态提示进行处理
let message = '';
if (status < 200 || status >= 300) {
// 处理http错误,抛到业务代码
message = showResState(status)
if (typeof res.data === 'string') {
res.data = {code: status, message: message}
} else {
res.data.code = status
res.data.message = message
}
}
return res.data;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});

function showResState(state) {
let message = '';
// 这里只做部分常见的示例,具体根据需要进行配置
switch (state) {
case 400:
message = '请求错误(400)'
break
case 401:
message = '未授权,请重新登录(401)'
break
case 403:
message = '拒绝访问(403)'
break
case 404:
message = '请求出错(404)'
break
case 500:
message = '服务器错误(500)'
break
case 501:
message = '服务未实现(501)'
break
case 502:
message = '网络错误(502)'
break
case 503:
message = '服务不可用(503)'
break
default:
message = `连接出错(${state})!`
}
return `${message},请检查网络或联系网站管理员!`
}



封装主体


这里为了方便起见,实例化对象处理的其实就是传入的配置文件,而封装的方法还是按照 axios 原生的方法处理的。为了方便做校验在接口上都统一增加了客户端发起请求的时间,以方便服务端做校验。配置参数可参照文档 axios 配置文档

// 构造函数
constructor(config) {
// 公共的 header
let defaultHeaders = {
'Content-Type': 'application/json;charset=UTF-8',
'Accept': 'application/json', // 通过头指定,获取的数据类型是JSON 'application/json, text/plain, */*',
'Authorization': null
}

let defaultConfig = {
headers: defaultHeaders
}

// 合并配置文件
if (config) {
for (let i in config) {
if (i === 'headers' && config.headers) {
for (let i in config.headers) {
defaultHeaders[i] = config.headers[i];
}
defaultConfig.headers = defaultHeaders;
} else {
defaultConfig[i] = config[i];
}
}
}
// 全局使用
this.init = axios;
this.config = defaultConfig;
}



get 方法的配置

// Get 请求
get(url, params = {}, headers = {}) {

params.time = Date.now();

// 合并 headers
if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}
return new Promise((resolve, reject) => {
// axios.get(url[, config])
this.init.get(url, {
...this.config,
...{params: params}
}).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}



post 请求

// POST 请求
post(url, params = {}, headers = {}) {

url = url + '?time=' + Date.now();

if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}

return new Promise((resolve, reject) => {
// axios.post(url[, data[, config]])
this.init.post(url, params, this.config).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}



PUT 请求

// PUT 请求
put(url, params = {}, headers = {}) {

url = url + '?time=' + Date.now();

if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}

return new Promise((resolve, reject) => {
// axios.put(url[, data[, config]])
this.init.put(url, params, this.config).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}



Delete 请求

// Delete 请求
delete(url, headers = {}) {
if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}
return new Promise((resolve, reject) => {
// axios.delete(url[, config])
this.init.delete(url, {
...this.config,
}).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}



>>使用


完整的代码的代码在文末会贴出来,这里简单说下如何使用

// @/api/index.js
import Http,{Axios} from '@/api/http'; // Axios 数据请求方法

// ① 可以使用文件中实例化的公共对象 Axios


// ②也可以单独实例化使用
const XHttp = new Http({
headers: {
'x-token': 'xxx'
}
});


export const getArticles = (params={}) => {
return XHttp.get('https://api.ycsnews.com/api/v1/blog/getArticles', params);
}

export const getArticle = (params={}) => {
return Axios.get('https://api.ycsnews.com/api/v1/blog/getArticles', params);
}



在页面中使用

// @/views/home.vue
import { getArticles,getArticle } from '@/api/index.js'

// 两个方法名差一个字母 's'
getArticle({id:1234444}).then((res) => {
console.log(res)
})
.catch(err => {
console.log(err)
})

getArticles({id:1234444}).then((res) => {
console.log(res)
})
.catch(err => {
console.log(err)
})



完整代码

// @/api/http.js
/**
* 说明:
* 1.多实例化,可以根据不同的配置进行实例化,满足不同场景的需求
* 2.多实例化情况下,可共用公共配置
* 3.请求拦截,响应拦截 对http错误提示进行二次处理
* 4.接口可单独配置 header 满足单一接口的特殊需求
* body 直传字符串参数,需要设置 headers: {"Content-Type": "text/plain"}, 传参:System.licenseImport('"'+this.code+'"');
* import Http,{Axios} from '../http'; // Http 类 和 Axios 数据请求方法 如无特殊需求 就使用实例化的 Axios 方法进行配置 有特殊需求再进行单独实例化
*
*
*/
import axios from "axios";

// 添加请求拦截器
axios.interceptors.request.use((config) => {
// 在发送请求之前做些什么 添加 token 等鉴权功能
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use((res) => {
const {status} = res;
// 对错误状态提示进行处理
let message = '';
if (status < 200 || status >= 300) {
// 处理http错误,抛到业务代码
message = showResState(status)
if (typeof res.data === 'string') {
res.data = {code: status, message: message}
} else {
res.data.code = status
res.data.message = message
}
}
return res.data;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});

function showResState(state) {
let message = '';
// 这里只做部分常见的示例,具体根据需要进行配置
switch (state) {
case 400:
message = '请求错误(400)'
break
case 401:
message = '未授权,请重新登录(401)'
break
case 403:
message = '拒绝访问(403)'
break
case 404:
message = '请求出错(404)'
break
case 500:
message = '服务器错误(500)'
break
case 501:
message = '服务未实现(501)'
break
case 502:
message = '网络错误(502)'
break
case 503:
message = '服务不可用(503)'
break
default:
message = `连接出错(${state})!`
}
return `${message},请检查网络或联系网站管理员!`
}

class Http {
constructor(config) {
// 公共的 header
let defaultHeaders = {
'Content-Type': 'application/json;charset=UTF-8',
'Accept': 'application/json', // 通过头指定,获取的数据类型是JSON 'application/json, text/plain, */*',
'Authorization': null
}

let defaultConfig = {
headers: defaultHeaders
}

// 合并配置文件
if (config) {
for (let i in config) {
if (i === 'headers' && config.headers) {
for (let i in config.headers) {
defaultHeaders[i] = config.headers[i];
}
defaultConfig.headers = defaultHeaders;
} else {
defaultConfig[i] = config[i];
}
}
}
this.init = axios;
this.config = defaultConfig;
}

// Get 请求
get(url, params = {}, headers = {}) {
// 合并 headers
if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}
return new Promise((resolve, reject) => {
// axios.get(url[, config])
this.init.get(url, {
...this.config,
...{params: params}
}).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}

// POST 请求
post(url, params = {}, headers = {}) {
if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}

return new Promise((resolve, reject) => {
// axios.post(url[, data[, config]])
this.init.post(url, params, this.config).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}

// PUT 请求
put(url, params = {}, headers = {}) {
if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}

return new Promise((resolve, reject) => {
// axios.put(url[, data[, config]])
this.init.put(url, params, this.config).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}


// Delete 请求
delete(url, headers = {}) {
if (headers) {
for (let i in headers) {
this.config.headers[i] = headers[i];
}
}
return new Promise((resolve, reject) => {
// axios.delete(url[, config])
this.init.delete(url, {
...this.config,
}).then(response => {
resolve(response);
})
.catch(error => {
reject(error)
}).finally(() => {
})
});
}
}

export default Http;

// 无特殊需求的只需使用这个一个对象即可 公共 header 可在此配置, 如需多个实例 可按照此方式创建多个进行导出
export const Axios = new Http({
baseURL:'https://docs.ycsnews.com',
headers: {
'x-http-token': 'xxx'
}
});











0 个评论

要回复文章请先登录注册