在这里插入代码片
## 创建实例
//这个写法作为我错误的记录,可以不看暂时
transformRequest: [(data: any) => {
if (!data) {
data = {
}
}
return qs.stringify(data)
}]
在我的项目里面,初始化配置里面进行handers的修改,例如:例如将一个请求为上传表单的请求头设置为:'Content-Type': 'multipart/form-data'
有可能不起作用的原因的就是这个属性导致的。
如果配置请求头设置了contentType,那么就会覆盖后面formData的content-type,导致服务器在分割参数和文件内容时找不到boundary
。报no multipart boundary was found
錯誤
const http = axios.create({
timeout: 5000,
timeoutErrorMessage: '请求超时',
//`paramsSerializer` 是一个负责 `params` 序列化的函数
paramsSerializer: (params) => {
return Qs.stringify(params, {
arrayFormat: 'brackets' })
}
//`transformResponse` 在传递给 then/catch 前,允许修改响应数据,对我的后面的切面设计有影响,就没有用
transformRequest: [(data: any) => {
return data
}]
优化请求(重复请求,取消上一次请求)
const pending: {
[prop: string]: any } = {
}
const CancelToken = axios.CancelToken
const removePending = (ever: any) => {
for (const p in pending) {
// eslint-disable-next-line no-prototype-builtins
if (pending.hasOwnProperty(p)) {
// 把参数带上
const url = `${
ever.url}?${
sequenceObject(ever.params)}&${
sequenceObject(ever.data)}`
if (p === `${
url}&${
ever.method}`) {
pending[p]()
delete pending[p]
}
}
}
}
请求拦截
请求时,如果没有请求头
Content-Type
数据,那就给他默认值为application/x-www-form-urlencoded;
并且可以将上传数据做一次安全的data转化:例如scope=ui&grant_type=password&username=admin&password=123456
加上请求头验证信息在,ajax 发送前,取消该接口的上一次请求,构造 ajax 请求标志,
http.interceptors.request.use((config: AxiosRequestConfig) => {
if (!config.headers['Content-Type']) {
config.headers['Content-Type'] = 'application/x-www-form-urlencoded;'
config.data = Qs.stringify(config.data, {
arrayFormat: 'brackets' })
}
config.headers.Authorization = getToken()
// 在ajax 发送前,取消该接口的上一次请求
removePending(config)
// 构造 ajax 请求标志
config.cancelToken = new CancelToken((cancel: any) => {
const url = `${
config.url}?${
sequenceObject(config.params)}&${
sequenceObject(config.data)}`
pending[`${
url}&${
config.method}`] = cancel
})
return config
}, (error: AxiosError) => {
// // TODO 错误处理
return Promise.reject(error)
})
响应拦截
拦截响应,如果请求错误则重新请求
这里是服务器响应数据之后,做一个切面处理。
首先可以请求成功之后,把请求标志从pending 队列中删除
做一个切面的统一处理,例如:如果返回的是esponse.data.code === 10000那就需要重新登陆。
返回拦截,做一个统一的处理返回错误
// 拦截响应,如果请求错误则重新请求
const retry = 2
const retryDelay = 500
http.interceptors.response.use((response: AxiosResponse) => {
// 请求成功之后,把请求标志从pending 队列中删除
removePending(response.config)
//做一个切面的统一处理
if (response.data.code === '10000' && response.config.url?.indexOf('/uaa/user/getUser') === -1) {
if ((store.state as any).tokenStatus) {
store.commit('clearAll')
router.replace('/newlogin')
const timer = setTimeout(() => {
console.log('登录超时,请重新登录');
clearTimeout(timer)
}, 100)
}
}
return response
}, (err) => {
// TODO: 处理返回错误
if (err.message) {
console.log('请求失败:', err)
app.$message({
type:"error",message:err.message,center:true})
}
const config = err.config
if (!config || !retry) {
return Promise.reject(err)
}
config.retryCount = config.retryCount || 0
console.log(`第${
config.retryCount + 2}次请求`)
if (config.retryCount >= retry) {
return Promise.reject(err)
}
config.retryCount += 1
const backoff = new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, retryDelay)
})
// Return the promise in which recalls axios to retry the request
return backoff.then(() => {
if (!(config.data instanceof FormData)) {
config.data = Qs.parse(config.data)
}
return axios(config)
})
})
qs.js - 更好的处理url参数
https://www.cnblogs.com/small-coder/p/9115972.html
axios中文文档
http://axios-js.com/zh-cn/docs/index.html#axios-create-config
表单(文件)上传的细节
https://blog.csdn.net/weixin_30521649/article/details/101482718