mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-04-05 19:41:57 +08:00
feat: 优化 request 异常处理
This commit is contained in:
parent
f636b37df9
commit
3f40ebe08b
@ -65,7 +65,6 @@ export const request = {
|
||||
// 特殊 code 处理逻辑
|
||||
},
|
||||
404(error) {
|
||||
|
||||
},
|
||||
default(error) {
|
||||
// 异常统一处理
|
||||
@ -75,6 +74,32 @@ export const request = {
|
||||
...otherConfigs
|
||||
}
|
||||
```
|
||||
|
||||
#### skipErrorHandler
|
||||
|
||||
- 类型: `boolean | string | number | array<string | number>`
|
||||
- 默认值: ``
|
||||
- 详情:
|
||||
|
||||
指定当前请求的某些错误状态不走 `errorHandler`,单独进行处理。如果设置为 `true`,当前请求的错误处理都不走 `errorHandler`。
|
||||
|
||||
- 示列:
|
||||
|
||||
```js
|
||||
import {request} from '@fesjs/fes';
|
||||
|
||||
request('/api/login', null, {
|
||||
skipErrorHandler: '110'
|
||||
}).then((res) => {
|
||||
// do something
|
||||
}).catch((err) => {
|
||||
// 这里处理 code 为 110 的异常
|
||||
// 此时 errorHandler[110] 函数不会生效,也不会执行 errorHandler.default
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 使用
|
||||
|
||||
### 发起一个普通 post 请求
|
||||
|
@ -39,6 +39,7 @@ import {
|
||||
|
||||
const CACHE_KEY_PREFIX = '__FES_REQUEST_CACHE:';
|
||||
const CACHE_TYPE = {
|
||||
merge: 'merge', // merge 重复请求
|
||||
ram: 'ram',
|
||||
session: 'sessionStorage',
|
||||
local: 'localStorage'
|
||||
@ -175,6 +176,11 @@ function handleCachingQueueError(ctx, config) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 添加一种 merge 类型
|
||||
* merge 当期所有请求,按顺序发起请求,只要有一个成功,所有请求都成功,并且跳过后续的请求。否则所有请求都失败
|
||||
* merge 错误提示
|
||||
*/
|
||||
|
||||
export default async (ctx, next) => {
|
||||
const { config } = ctx;
|
||||
@ -200,11 +206,14 @@ export default async (ctx, next) => {
|
||||
const requestdata = checkHttpRequestHasBody(config.method) ? config.data : config.params;
|
||||
if (!ctx.error && ctx.response && canCache(requestdata) && canCache(ctx.response.data)) {
|
||||
handleCachingQueueSuccess(ctx, config, ctx.response.data);
|
||||
setCacheData({
|
||||
key: ctx.key,
|
||||
data: ctx.response.data,
|
||||
...config.cache
|
||||
});
|
||||
|
||||
if (config.cache.cacheType !== CACHE_TYPE.merge) {
|
||||
setCacheData({
|
||||
key: ctx.key,
|
||||
data: ctx.response.data,
|
||||
...config.cache
|
||||
});
|
||||
}
|
||||
} else {
|
||||
handleCachingQueueError(ctx, config);
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ function getRequestInstance() {
|
||||
addRequestInterceptors(instance, requestInterceptors);
|
||||
addResponseInterceptors(instance, responseInterceptors);
|
||||
|
||||
// 洋葱模型内部应该这是对数据的处理,避免有副作用调用
|
||||
scheduler.use(paramsProcess)
|
||||
.use(genRequestKey)
|
||||
.use(cacheControl)
|
||||
@ -120,6 +121,52 @@ function createContext(userConfig) {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function getResponseCode(response) {
|
||||
if (response) {
|
||||
if (response._rawData) return response._rawData.code;
|
||||
if (response.data) return response.data.code;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function skipErrorHandlerToObj(skipErrorHandler = []) {
|
||||
if (!Array.isArray(skipErrorHandler)) {
|
||||
skipErrorHandler = [skipErrorHandler];
|
||||
}
|
||||
|
||||
return skipErrorHandler.reduce((acc, cur) => {
|
||||
acc[cur] = true;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function handleRequestError({
|
||||
errorHandler = {},
|
||||
error,
|
||||
response,
|
||||
config
|
||||
}) {
|
||||
// 跳过所有错误类型处理
|
||||
if (config.skipErrorHandler === true) return;
|
||||
|
||||
const skipObj = skipErrorHandlerToObj(config.skipErrorHandler);
|
||||
const resCode = getResponseCode(response);
|
||||
|
||||
let errorKey = 'default';
|
||||
if (resCode && errorHandler[resCode]) {
|
||||
errorKey = resCode;
|
||||
} else if (error.type && errorHandler[error.type]) {
|
||||
errorKey = error.type;
|
||||
} else if (error.response && errorHandler[error.response.status]) {
|
||||
errorKey = error.response.status;
|
||||
}
|
||||
|
||||
if (!skipObj[errorKey] && errorHandler[errorKey]) {
|
||||
errorHandler[errorKey](error);
|
||||
}
|
||||
}
|
||||
|
||||
export const request = (url, data, options = {}) => {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
@ -136,6 +183,7 @@ export const request = (url, data, options = {}) => {
|
||||
if (!context.error) {
|
||||
return context.config.useResonse ? context.response : context.response.data;
|
||||
}
|
||||
handleRequestError(context);
|
||||
return Promise.reject(context.error);
|
||||
});
|
||||
};
|
||||
|
@ -1,41 +1,16 @@
|
||||
import { isObject } from './helpers';
|
||||
|
||||
function handleAbnormalCode(errorHandler = {}, code, response) {
|
||||
if (errorHandler[code]) {
|
||||
errorHandler[code](response.data);
|
||||
} else if (errorHandler.default) {
|
||||
// 处理其他异常
|
||||
errorHandler.default({
|
||||
response
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleRequestError(errorHandler = {}, error) {
|
||||
if (error.type && errorHandler[error.type]) {
|
||||
errorHandler[error.type](error);
|
||||
} else if (error.response && errorHandler[error.response.status]) {
|
||||
errorHandler[error.response.status](error);
|
||||
} else if (errorHandler.default) {
|
||||
errorHandler.default(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 错误处理等副作用网上提
|
||||
export default async (ctx, next) => {
|
||||
const {
|
||||
error,
|
||||
errorHandler = {},
|
||||
response,
|
||||
config
|
||||
} = ctx;
|
||||
if (!config.closeResDataCheck && response && isObject(response.data)) {
|
||||
const code = response.data.code;
|
||||
if (code !== '0') {
|
||||
handleAbnormalCode(errorHandler, code, response);
|
||||
ctx.error = response; // code 不为零进入 reject
|
||||
}
|
||||
} else if (error) {
|
||||
handleRequestError(errorHandler, error);
|
||||
}
|
||||
|
||||
await next();
|
||||
|
@ -1,7 +1,7 @@
|
||||
export const request = {
|
||||
errorHandler: {
|
||||
111(responseData) {
|
||||
console.log(responseData);
|
||||
111() {
|
||||
console.log('root:111');
|
||||
},
|
||||
500() {
|
||||
console.log('500 error');
|
||||
|
@ -12,18 +12,13 @@
|
||||
}
|
||||
</config>
|
||||
<script>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter, request } from '@fesjs/fes';
|
||||
import { ref } from 'vue';
|
||||
import { request } from '@fesjs/fes';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const fes = ref('fes upgrade to vue3');
|
||||
const rotate = ref(90);
|
||||
const router = useRouter();
|
||||
onMounted(() => {
|
||||
console.log(router);
|
||||
console.log('mounted1!!');
|
||||
});
|
||||
const clickIcon = () => {
|
||||
console.log('click Icon');
|
||||
};
|
||||
@ -58,20 +53,28 @@ export default {
|
||||
// });
|
||||
// }, 3200);
|
||||
|
||||
// request('/api', null, {
|
||||
// cache: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// request('/api', null, {
|
||||
// cache: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// request('/api', null, {
|
||||
// cache: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
|
||||
request('/api', null, {
|
||||
cache: true
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
request('/api', null, {
|
||||
cache: true
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
request('/api', null, {
|
||||
cache: true
|
||||
// skipErrorHandler: [500]
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
}).catch((err) => {
|
||||
console.log('inner error', err);
|
||||
});
|
||||
return {
|
||||
fes,
|
||||
|
Loading…
x
Reference in New Issue
Block a user