为了使项目里的接口调用起来更方便,接口归类更加分明,需要对axios进行封装,下面我将会讲解下我在项目中对axios的封装以及处理:
该目录是我们的项目目录,utils文件下的request.js是封装axios的文件,api问下下放了各个模块的接口文件,这样归类更容易区分。
一、在request.js文件里对axios进行统一封装
第一步先引入axios依赖,iview的提示框引入在这里只是举例,各位可以根据自己的项目框架引入自己的提示框
import axios from 'axios';
import {Message} from 'iview'; // 引入iview的message组件,为了统一封装报错时的提示
定义下在接口呈现各个状态时的不同提示:
const statusDic = {
400: '操作失败',
401: '登录超时,请重新登录',
403: '拒绝访问',
404: '网络资源无法访问',
405: '请求方法不支持',
408: '请求超时,请稍后重试',
500: '服务器内部错误',
501: '服务未实现',
502: '网关错误',
503: '服务不可用',
504: '网关超时',
505: 'HTTP版本不受支持'
}
创建axios实例,请求超时时间各位可以根据自己的实际情况设置,pc端可以稍微设置长一点,移动端可以设置稍微短一点:
// 创建axios实例
const service = axios.create({
timeout: 30000, // 请求超时时间30秒
withCredentials: true // 全局默认配置设置cookies
});
request拦截器处理:
// request拦截器
service.interceptors.request.use(config => {
config.headers = {
'Content-Type': config.contentType || 'application/x-www-form-urlencoded'
}
if (
config.headers['Content-Type'] === 'application/x-www-form-urlencoded' &&
!config.isFormData &&
config.method !== 'get'
) {
const paramsArray = []
// 拼接参数
Object.keys(config.data).forEach(key =>
paramsArray.push(`${key}=${config.data[key]}`)
)
config.data = paramsArray.join('&')
} else if (
config.headers['Content-Type'] === 'application/json' &&
config.method !== 'get'
) {
config.data = JSON.stringify(config.data)
}
// 以http开头则放过
if (config.url.indexOf('http') === 0) {
return config;
}
// 以dsb开头向后端发送的请求,本地json文件请求头与前端域名保持一致(以下判断处理为我公司业务逻辑,我们公司的项目前后端分离,域名可相同也可不相同,不相同的时候需要区别加载的是json文件还是后端的接口)
let reg = /^\/dsb\/.*$/;
if (reg.test(config.url)) {
config.url = process.env.BASE_API + config.url;
}
return config;
}, error => Promise.reject(error));
respone拦截器处理:
// response 拦截器
axios.interceptors.response.use(
(response, config) => Promise.resolve(response),
error => {
// 前端自动放弃请求提示
if (error.code && error.code === 'ECONNABORTED') {
Message.error(statusDic['408'])
return Promise.reject(error)
}
if (error.response && error.response.status) {
const {status} = error.response
if (Object.keys(statusDic).indexOf(`${status}`) !== -1) {
// 该提示框为iview框架的提示框,请自行更换自己的
Message.error(statusDic[status])
if (status == 401) {
// 登录超时时需跳转到登录页面,或者退出应用,根据业务自行补上
}
}
}
return Promise.reject(error)
}
)
统一封装 get ,post,patch,put请求:
const AJAXS = {} // 缓存ajax用于abort
const {CancelToken} = axios
/**
* 缓存ajax对象,用来abort
* @param url
* @param ajax
*/
const addAbortAjax = (url, ajax) => {
AJAXS[url] = ajax
}
const deleteAbortAjax = url => {
delete AJAXS[url]
}
/**
* 统一封装 get ,post,patch,put请求
*/
const ajaxMethod = ['get', 'post', 'patch', 'put']
const $axios = {}
ajaxMethod.forEach(method => {
$axios[method] = function(url, data = {}, formatter = noop, config = {}) {
const cache = config._cacheAjax
cache && delete config._cacheAjax
if (cache) {
config.cancelToken = new CancelToken(cancel => {
addAbortAjax(url, cancel)
})
}
const authFormatter = function(res) {
return formatter(res)
}
return new Promise((resolve, reject) => {
if (method === 'get') {
config.beforeSend && config.beforeSend()
config.params = data
axios[method](`${url}?_=${Date.now()}`, config)
.then(response => {
config.complete && config.complete()
deleteAbortAjax(url)
resolve(response)
})
.catch(error => {
config.complete && config.complete()
reject(error)
deleteAbortAjax(url)
})
} else {
config.beforeSend && config.beforeSend()
axios[method](url, data, config)
.then(response => {
deleteAbortAjax(url)
config.complete && config.complete()
resolve(response)
})
.catch(error => {
config.complete && config.complete()
reject(error)
deleteAbortAjax(url)
})
}
})
}
})
最后将axios实例暴露出去:
export default service
用法:先对接口进行封装
import _ from 'lodash'
import $axios from '@/utils/request'
export default {
/**
*账号登录
*/
login (param, config) {
return $axios
.post('/api/auth/login', param, res => res, config)
.then(res => _.get(res, 'data'))
}
}
同级新增index.js文件:
import login from './login'
export {login}
在页面中调用
import {login} from '@/api/login'
login.login().then(response => {
})