feat: 适配器异常处理成响应异常

pull/41/head
zjx0905 2023-04-11 13:13:45 +08:00
parent adb9dbe88f
commit be17ba7e68
7 changed files with 102 additions and 36 deletions

2
.gitignore vendored
View File

@ -19,7 +19,7 @@ lib/
*.test.js
*.test.d.ts
*.test.js.map
coverage
.coverage
# eslint
.eslintcache

View File

@ -2,6 +2,7 @@ import {
isEmptyArray,
isFunction,
isPlainObject,
isString,
isUndefined,
} from './helpers/isTypes';
import { assert } from './helpers/error';
@ -57,6 +58,19 @@ export interface AxiosAdapterResponseError extends AnyObject {
*
*/
headers: AnyObject;
/**
*
*/
data?: {
/**
*
*/
errMsg: string;
/**
* Errno
*/
errno: number;
};
}
export interface AxiosAdapterRequestConfig extends AnyObject {
@ -253,22 +267,25 @@ export function createAdapter(platform: AxiosPlatform) {
return download(options);
}
function transformResult(result: AnyObject): void {
result.status =
result.status ??
result.statusCode ??
(isUndefined(result.data) ? 400 : 200);
result.statusText =
result.status === 200
? 'OK'
: result.status === 400
? 'Bad Adapter'
: result.errMsg;
result.headers = result.headers || result.header;
function transformResponse(response: AnyObject): void {
response.status = response.status ?? response.statusCode;
response.statusText = 'OK';
if (result.statusCode) delete result.statusCode;
if (result.errMsg) delete result.errMsg;
if (result.header) delete result.header;
if (isUndefined(response.status)) {
response.status = 400;
response.statusText = 'Fail Adapter';
}
response.headers = response.headers ?? response.header ?? {};
if (isUndefined(response.data) && isString(response.errMsg)) {
response.data = {
errMsg: response.errMsg,
errno: response.errno,
};
}
cleanResponse(response, ['statusCode', 'errMsg', 'errno', 'header']);
}
function transformOptions(
@ -278,11 +295,11 @@ export function createAdapter(platform: AxiosPlatform) {
...config,
header: config.headers,
success(response): void {
transformResult(response);
transformResponse(response);
config.success(response);
},
fail(error: AxiosAdapterResponseError): void {
transformResult(error);
transformResponse(error);
config.fail(error);
},
};
@ -297,9 +314,16 @@ export function createAdapter(platform: AxiosPlatform) {
response.apFilePath,
};
if (response.tempFilePath) delete response.tempFilePath;
if (response.apFilePath) delete response.apFilePath;
if (response.filePath) delete response.filePath;
cleanResponse(response, ['tempFilePath', 'apFilePath', 'filePath']);
}
/**
* response key
*/
function cleanResponse(response: AnyObject, keys: string[]) {
for (const key of keys) {
if (key in response) delete response[key];
}
}
return adapter;

View File

@ -186,7 +186,7 @@ export interface AxiosResponse<
export interface AxiosResponseError extends AxiosAdapterResponseError {
/**
* fail
*
*/
isFail: true;
/**

View File

@ -4,6 +4,7 @@ import {
AxiosAdapterRequestMethod,
AxiosAdapterResponse,
AxiosAdapterResponseError,
AxiosAdapterTask,
} from '../adapter';
import {
AxiosProgressCallback,
@ -49,7 +50,16 @@ export function request(config: AxiosRequestConfig) {
fail,
};
const adapterTask = adapter!(adapterConfig);
let adapterTask: AxiosAdapterTask;
try {
adapterTask = adapter!(adapterConfig);
} catch {
fail({
status: 400,
statusText: 'Bad Adapter',
headers: {},
});
}
function success(_: AxiosAdapterResponse): void {
const response = _ as AxiosResponse;

View File

@ -253,12 +253,14 @@ describe('src/adapter.ts', () => {
};
const p2 = {
...p1,
request: vi.fn(({ fail }) => fail({ data: { result: null } })),
request: vi.fn(({ fail }) =>
fail({ status: 500, data: { result: null } }),
),
};
const p3 = {
...p1,
request: vi.fn(({ fail }) =>
fail({ statusCode: 500, header: {}, errMsg: 'request:fail' }),
fail({ errMsg: 'request:fail', errno: 1000 }),
),
};
const c1 = {
@ -269,9 +271,9 @@ describe('src/adapter.ts', () => {
fail: (response: any) => {
expect(response).toMatchInlineSnapshot(`
{
"headers": undefined,
"headers": {},
"status": 400,
"statusText": "Bad Adapter",
"statusText": "Fail Adapter",
}
`);
},
@ -284,8 +286,8 @@ describe('src/adapter.ts', () => {
"data": {
"result": null,
},
"headers": undefined,
"status": 200,
"headers": {},
"status": 500,
"statusText": "OK",
}
`);
@ -296,9 +298,13 @@ describe('src/adapter.ts', () => {
fail: (response: any) => {
expect(response).toMatchInlineSnapshot(`
{
"data": {
"errMsg": "request:fail",
"errno": 1000,
},
"headers": {},
"status": 500,
"statusText": "request:fail",
"status": 400,
"statusText": "Fail Adapter",
}
`);
},

View File

@ -37,16 +37,42 @@ describe('src/core/dispatchRequest.ts', () => {
).not.toThrowError();
});
test('坏的适配器', () => {
expect(() =>
test('坏的适配器应该抛出异常', () => {
expect(
dispatchRequest({
adapter: () => {
throw 'bad adapter';
},
url: '/',
method: 'get',
}),
).toMatchInlineSnapshot('[Function]');
}).catch((e) => ({ ...e })),
).resolves.toMatchInlineSnapshot(`
{
"config": {
"adapter": [Function],
"data": undefined,
"headers": undefined,
"method": "get",
"url": "",
},
"request": undefined,
"response": {
"config": {
"adapter": [Function],
"data": undefined,
"headers": undefined,
"method": "get",
"url": "",
},
"data": undefined,
"headers": {},
"isFail": true,
"request": undefined,
"status": 400,
"statusText": "Bad Adapter",
},
}
`);
});
test('应该支持转换 URL', () => {

View File

@ -10,7 +10,7 @@ export default defineConfig({
},
coverage: {
provider: 'istanbul',
reportsDirectory: resolve('test/coverage'),
reportsDirectory: resolve('test/.coverage'),
enabled: false,
include: ['src/**/*.ts'],
},