前言
距离上一次遇到耗时半天解决bug写已经过去两个月了......
这次的场景是这样:正常的前后端交互是有固定的格式,来方便前端做统一拦截处理的,但是有一种例外的场景,那就是文件
这是最早的简单拦截器,也处理了下载,安全稳定用了2年,这次有个小伙伴有个需求需要预览,那我这个处理逻辑就没办法正确的拿到返回数据了。
// 响应拦截器
responseInterceptors: [
(response: AxiosResponse) => {
// 拦截响应数据,进行个性化处理
const { data } = response as unknown as ResponseStructure;
if (response.status !== 200) {
return Promise.reject({ response: response }) as any;
} else {
if (data.code === '00000000') {
return response.data;
} else {
if ((response.config as { isDownload: boolean })?.isDownload) {
downloadBlob(response);
return true;
}
}
return Promise.reject({ response: response });
}
},
],
请求代码编写
export async function downloadFile(
systemcode: string,
bucketName: string,
fileKey: string,
view: boolean,
) {
return request<string[]>('/api/file/download', {
method: 'GET',
params: { systemcode, bucketName, fileKey, view },
isDownload: true,
});
}
export async function preview(
systemcode: string,
bucketName: string,
fileKey: string,
view: boolean,
) {
const response = await request('/api/file/download', {
method: 'GET',
params: { systemcode, bucketName, fileKey, view },
isNoCode: true,
});
console.log(response);
return response;
}
按照拦截器可以看出,代码会被拒绝然后抛出,也就是.catch可以获取到 (我:那你就在.catch里面写你的展示逻辑不就好了)
1 诡异的undefined
其实问题就是后端返回的格式数据结构,那就加一个isNocode来判断一下,返回就好了
// 拦截修改部分
if (response.status !== 200) {
return Promise.reject({ response: response }) as any;
} else {
if (data.code === '00000000') {
return response.data;
} else {
if ((response.config as { isNoCode: boolean })?.isNoCode) {
return response.data;
}
// return Promise.reject({ response: response });
}
return Promise.reject({ response: response });
}
// 请求代码
export async function preview(
systemcode: string,
bucketName: string,
fileKey: string,
view: boolean,
) {
const response = await request('/api/file/download', {
method: 'GET',
params: { systemcode, bucketName, fileKey, view },
isNoCode: true,
});
console.log(response);
return response;
}
好好好,在线在新人面前翻车了,然后我说我一会看看-。-,结果调试了老半天
2 调试过程
2.1 怀疑上了Promise
一开始在想是不是因为return 的不是reaolve的问题,但是没去改,而是去看调试了平常的接口,不然直接破案了,我不可能去管为啥的,只要把上面代码的return response.data用Promise.resolve包裹就好了。
const requestParams = { ...params, systemCode, bucketPkId, dirKey };
const dd = await request<TableType.TableRequest<FileListTable>>('/api/file/list', {
method: 'GET',
params: isSortToParams(requestParams, sort),
});
console.log(dd);
居然dd有值,然后我就怀疑是不是umi或者axios对content-type为json的做了特殊处理 经过我各种调试后,giao没有一点头绪,为什么是undefined
2.2 直接改掉拦截器的返回
if (response.status !== 200) {
return Promise.reject({ response: response }) as any;
} else {
if (data.code === '00000000') {
return response.data;
} else {
if ((response.config as { isNoCode: boolean })?.isNoCode) {
return '123'
}
}
return Promise.reject({ response: response });
}
还是undefined,直接当场裂开,然后就去翻axios的文档,发现没有介绍什么东西
2.3 意外破案
调试太多次了,调试过快,加冬天偏冷,手一抖点了按行执行,意外进了pulgin-request的文件
在这个步骤我也点了三遍,一直没有反应过来图3的三元表达式 getResponse为false,然后我看res有值没毛病,为啥到下一步代码就又为undefined了-。-
(所以经常就是去抽根烟回来突然就有了灵感,一直重复做一件事,思维会定式)
resolve(getResponse ? res : res.data);
我是一直到调试其它接口的时候发现了,返回的是res.data才是对的,才反应过来
3 总结与解决方式
3.1 结论
request这边有封装一层,取的是return里面的data,正好以前的代码返回格式
response.data里面还有data,起初的目标就是为了去掉最外层data不要每次都const data = res.data或者.then里面写if res.code==="0000000" 这种代码我想很多人都有见过,也是后面慢慢的开始用统一拦截
故而没有一点问题在之前和后端配合的情况
3.2 结论语方案
3.2.1 暂时没找到
而现在流返回直接没有了这个返回结果格式,根据上面的分析,传参只要有办法把getResponse变为true就行了
3.2.2 response
if (response.status !== 200) {
return Promise.reject({ response: response }) as any;
} else {
if (data.code === '00000000') {
return response.data;
} else {
if ((response.config as { isNoCode: boolean })?.isNoCode) {
return response
}
}
return Promise.reject({ response: response });
}
3.3.3 最终修改
responseInterceptors: [
(response: AxiosResponse) => {
// blob类型另外处理
if (
response.headers?.['content-type'] &&
!response.headers?.['content-type'].includes('application/json')
) {
// 下载情况已特殊处理
if ((response.config as { isDownload: boolean })?.isDownload) {
downloadBlob(response);
return true;
} else {
// 直接返回后端返回的数据
return response;
}
}
// 拦截响应数据,进行个性化处理
const { data } = response as unknown as ResponseStructure;
if (response.status !== 200) {
return Promise.reject({ response: response }) as any;
} else {
if (data.code === '00000000') {
return Promise.resolve(response.data);
}
return Promise.reject({ response: response });
}
},
],
因为后端可能还会返回图片,那总不能再单独处理,那就把json的当成正常和后端处理的情况,不是json的都是其它情况,数据丢出到交互那边自行处理