如果有mockjs操作 会影响 axios 的默认配置
会对发出请求的 url 进行如下转码操作
lib\helpers\buildURL.js
encodeURIComponent(val).
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%20/g, '+').
replace(/%5B/gi, '[').
replace(/%5D/gi, ']');
上传 FormData数据
axios 可以自动判断上传的数据是否是formdata,从而修改 content-type, 只需要设置 request config 的 data { data: FormData }
终止请求
取消一个已经发出的请求
const controller = new AbortController(); // 目前看源码是 axios 重写了AbortController方法【20220930】
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//
});
// 取消成功后 如果用了 response 拦截 需要在 error 回调中处理
controller.abort()
简单封装
import { v1 as uuId } from 'uuid'
import axios from 'axios'
import { Message } from 'element-ui'
import { getDomain } from '@/utils/common'
/**
* @des get 方式,参数放 params
* @des post put 等方式,参数放 data
* @des post patch 等方式有 params data 参数,当只传 params 时,会转换赋值到data上 与axios需要的参数一致
* @des 这里默认返回的数据结构 { code: '自定义状态码 当前项目 1 表示成功', data: '结果', msg: '结果描述' }
*/
const httpService = axios.create({
withCredentials: true, // 跨域携带cookie,设置为true,服务器也需要设置,一般不推荐如此使用
timeout: 0,
headers: { Authorization: 'hewitt' }
})
httpService.interceptors.request.use((cfg) => {
const { url, method, params, data, commonPre = '/api' } = cfg
/* 重置或配置 headers 的值 */
cfg.headers.uuid = uuId().replace(/-/g, '')
cfg.headers.token = '' || '' // 注意传token时不要出现 undefined 都会被识别成字符串带入校验,如果没有就传空或者不设备这个头
/**
* @des 处理url中带参数(例:/xx/:id/xx/ -> /xx/123/xx/) 这里的参数要带在 params 里,(不推荐这种写法240220)
*/
if (/:/.test(url)) {
const urlParam = /\/:([^/]+)(?:\/|$)/.exec(url)[1]
cfg.url = url.replace(`:${urlParam}`, params[urlParam])
delete cfg.params[urlParam]
}
/**
* @des 统一处理 formData 传参
* 定义接口时设置 formData: true; 配置 data 字段
*/
if (formData) {
const formData = new FormData()
Object.keys(data).forEach(k => {
formData.append(k, data[k])
})
cfg.data = formData
}
/**
* @des 如果没有配置反向代理,可直接加地址
*/
// console.log('NODE_ENV', process.env.NODE_ENV)
/* 公共前缀默认 api */
cfg.baseURL = getDomain()
return cfg
}, (error) => {
/* 这里基本不会进入,一般在 response 的捕获中处理 */
return Promise.reject(error)
})
httpService.interceptors.response.use((res) => {
const { config, data } = res
/**
* 注意 showSuccessMsg 参数实在 api文件里面的方法中传递的,是和url同一级
* code === 'xxx 根据不同的后端数据结构来定义'
* 一般不统一处理成功,只处理报错信息显示
**/
if (config.showSuccessMsg && data.code === 1) {
Message({
message: data.msg,
type: 'success',
duration: 2000
})
}
/*
excludeCode 默认 false,表示返回的数据格式是符合统一标准的;
当设置为true时,表示不对code检测判断错误,一般用于返回数据格式不规范(没有返回code)时使用
*/
if (data.code !== 1 && !config.excludeCode) {
/* 这里的错误,只做提示信息的统一处理,因为每一个地方的错误处理业务不同 */
Message({
message: data.msg,
type: 'error',
duration: 2000
})
return Promise.reject(res.data)
}
// 所有操作成功,然后返回 这里成功,code也不做返回 只返回成功的数据
return res.data.data
}, (error) => {
/**
* 接口报错 404等 会进入
* request 中抛出的错误、reject 会进入 这里的 error 对象就是,自己抛出的错误对象,自己封装的 error 对象 错误信息字段务必用 message 与 axios 封装的一致
* 这里如果是axios 捕获的超时或服务器报错 会返回一个 封装好的 error 对象, error.message
* 这里可以用 error.toJSON() 打印 error中的一些信息 比如 error.code
*
*/
if (error.code === 404) {
Message({ message: '接口未找到', type: 'error', duration: 2000 })
} else {
Message({ message: error.message, type: 'error', duration: 2000 })
}
/* 这里的返回 有需要 可以在业务代码的 catch 中获取 再进行特殊的异常处理 */
return Promise.reject(error)
})
/* 公共前缀 */
export const httpCommonManage = (params) => {
params.commonPre = '/some'
return httpService(params)
}
export default httpService