refactor: 重写 AxiosError 类型

pull/41/head
zjx0905 2023-04-05 16:35:25 +08:00
parent f1c0f348be
commit cf2e46476d
5 changed files with 36 additions and 34 deletions

View File

@ -104,15 +104,15 @@ export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
} }
export interface AxiosAdapterRequest { export interface AxiosAdapterRequest {
(config: AxiosAdapterBaseOptions): AxiosAdapterTask | void; (config: AxiosAdapterBaseOptions): AxiosAdapterTask;
} }
export interface AxiosAdapterUpload { export interface AxiosAdapterUpload {
(config: AxiosAdapterUploadOptions): AxiosAdapterTask | void; (config: AxiosAdapterUploadOptions): AxiosAdapterTask;
} }
export interface AxiosAdapterDownload { export interface AxiosAdapterDownload {
(config: AxiosAdapterDownloadOptions): AxiosAdapterTask | void; (config: AxiosAdapterDownloadOptions): AxiosAdapterTask;
} }
export interface AxiosPlatform { export interface AxiosPlatform {
@ -121,14 +121,14 @@ export interface AxiosPlatform {
download: AxiosAdapterDownload; download: AxiosAdapterDownload;
} }
export interface AxiosAdapterTask { export type AxiosAdapterTask = {
abort?(): void; abort?(): void;
onProgressUpdate?(callback: AxiosProgressCallback): void; onProgressUpdate?(callback: AxiosProgressCallback): void;
offProgressUpdate?(callback: AxiosProgressCallback): void; offProgressUpdate?(callback: AxiosProgressCallback): void;
} } | void;
export interface AxiosAdapter { export interface AxiosAdapter {
(config: AxiosAdapterRequestConfig): AxiosAdapterTask | void; (config: AxiosAdapterRequestConfig): AxiosAdapterTask;
} }
export function getAdapterDefault(): AxiosAdapter | undefined { export function getAdapterDefault(): AxiosAdapter | undefined {
@ -171,7 +171,7 @@ export function createAdapter(platform: AxiosPlatform): AxiosAdapter {
assert(isFunction(platform.upload), 'upload 不是一个 function'); assert(isFunction(platform.upload), 'upload 不是一个 function');
assert(isFunction(platform.download), 'download 不是一个 function'); assert(isFunction(platform.download), 'download 不是一个 function');
function adapter(config: AxiosAdapterRequestConfig): AxiosAdapterTask | void { function adapter(config: AxiosAdapterRequestConfig): AxiosAdapterTask {
const baseOptions = transformOptions(config); const baseOptions = transformOptions(config);
switch (config.type) { switch (config.type) {
@ -189,14 +189,14 @@ export function createAdapter(platform: AxiosPlatform): AxiosAdapter {
function callRequest( function callRequest(
request: AxiosAdapterRequest, request: AxiosAdapterRequest,
baseOptions: AxiosAdapterBaseOptions, baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterTask | void { ): AxiosAdapterTask {
return request(baseOptions); return request(baseOptions);
} }
function callUpload( function callUpload(
upload: AxiosAdapterUpload, upload: AxiosAdapterUpload,
baseOptions: AxiosAdapterBaseOptions, baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterTask | void { ): AxiosAdapterTask {
const { fileName, filePath, fileType, ...formData } = const { fileName, filePath, fileType, ...formData } =
baseOptions.data as AxiosRequestFormData; baseOptions.data as AxiosRequestFormData;
const options = { const options = {
@ -214,7 +214,7 @@ export function createAdapter(platform: AxiosPlatform): AxiosAdapter {
function callDownload( function callDownload(
download: AxiosAdapterDownload, download: AxiosAdapterDownload,
baseOptions: AxiosAdapterBaseOptions, baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterTask | void { ): AxiosAdapterTask {
const options = { const options = {
...baseOptions, ...baseOptions,
filePath: baseOptions.params?.filePath, filePath: baseOptions.params?.filePath,

View File

@ -11,7 +11,7 @@ import { mergeConfig } from './core/mergeConfig';
import { AxiosAdapter, createAdapter, AxiosPlatform } from './adapter'; import { AxiosAdapter, createAdapter, AxiosPlatform } from './adapter';
import defaults from './defaults'; import defaults from './defaults';
export interface AxiosInstanceDefaults extends AxiosRequestHeaders { export interface AxiosInstanceDefaults extends AxiosRequestConfig {
headers: Required<AxiosRequestHeaders>; headers: Required<AxiosRequestHeaders>;
} }

View File

@ -7,15 +7,15 @@ export type AxiosErrorResponse = AxiosResponse | AxiosResponseError;
class AxiosError extends Error { class AxiosError extends Error {
public config: AxiosRequestConfig; public config: AxiosRequestConfig;
public request?: AxiosAdapterTask; public request: AxiosAdapterTask;
public response?: AxiosErrorResponse; public response: AxiosErrorResponse;
public constructor( public constructor(
message: string, message: string,
config: AxiosRequestConfig, config: AxiosRequestConfig,
request?: AxiosAdapterTask, response: AxiosErrorResponse,
response?: AxiosErrorResponse, request: AxiosAdapterTask,
) { ) {
super(message); super(message);
@ -30,10 +30,10 @@ class AxiosError extends Error {
export function createError( export function createError(
message: string, message: string,
config: AxiosRequestConfig, config: AxiosRequestConfig,
request?: AxiosAdapterTask, response: AxiosErrorResponse,
response?: AxiosErrorResponse, request: AxiosAdapterTask,
): AxiosError { ): AxiosError {
const axiosError = new AxiosError(message, config, request, response); const axiosError = new AxiosError(message, config, response, request);
cleanStack(axiosError); cleanStack(axiosError);
return axiosError; return axiosError;
} }

View File

@ -5,7 +5,6 @@ import {
AxiosAdapterRequestMethod, AxiosAdapterRequestMethod,
AxiosAdapterResponse, AxiosAdapterResponse,
AxiosAdapterResponseError, AxiosAdapterResponseError,
AxiosAdapterTask,
} from '../adapter'; } from '../adapter';
import { import {
AxiosProgressCallback, AxiosProgressCallback,
@ -56,9 +55,7 @@ export function request<TData = unknown>(
fail, fail,
}; };
const adapterTask = config.adapter!(adapterConfig) as const adapterTask = config.adapter!(adapterConfig);
| AxiosAdapterTask
| undefined;
function success(_: AxiosAdapterResponse<TData>): void { function success(_: AxiosAdapterResponse<TData>): void {
const response = _ as AxiosResponse<TData>; const response = _ as AxiosResponse<TData>;
@ -75,15 +72,18 @@ export function request<TData = unknown>(
} }
function fail(_: AxiosAdapterResponseError): void { function fail(_: AxiosAdapterResponseError): void {
const error = _ as AxiosResponseError; const responseError = _ as AxiosResponseError;
error.isFail = true; responseError.isFail = true;
error.config = config; responseError.config = config;
error.request = adapterTask; responseError.request = adapterTask;
catchError('网络错误', error); catchError('网络错误', responseError);
} }
function catchError(message: string, response?: AxiosErrorResponse): void { function catchError(
reject(createError(message, config, adapterTask, response)); message: string,
errorResponse: AxiosErrorResponse,
): void {
reject(createError(message, config, errorResponse, adapterTask));
} }
if (isPlainObject(adapterTask)) { if (isPlainObject(adapterTask)) {

View File

@ -5,28 +5,30 @@ import { createError, isAxiosError } from 'src/core/createError';
describe('src/core/createError.ts', () => { describe('src/core/createError.ts', () => {
test('应该支持空参数', () => { test('应该支持空参数', () => {
const c = {}; const c = {};
const err = createError('error', c); const r = {} as any;
const err = createError('error', c, r);
expect(err.message).toBe('error'); expect(err.message).toBe('error');
expect(err.config).toBe(c); expect(err.config).toBe(c);
expect(err.response).toBe(r);
expect(checkStack(err)).toBeTruthy(); expect(checkStack(err)).toBeTruthy();
}); });
test('应该支持传入更多参数', () => { test('应该支持传入更多参数', () => {
const c = {}; const c = {};
const req = {};
const res = {}; const res = {};
const err = createError('error', c, req, res as any); const req = {} as any;
const err = createError('error', c, res as any, req);
expect(err.message).toBe('error'); expect(err.message).toBe('error');
expect(err.config).toBe(c); expect(err.config).toBe(c);
expect(err.request).toBe(req);
expect(err.response).toBe(res); expect(err.response).toBe(res);
expect(err.request).toBe(req);
}); });
test('应该正确判断 AxiosError', () => { test('应该正确判断 AxiosError', () => {
expect(isAxiosError(0)).toBeFalsy(); expect(isAxiosError(0)).toBeFalsy();
expect(isAxiosError(new Error())).toBeFalsy(); expect(isAxiosError(new Error())).toBeFalsy();
expect(isAxiosError(createError('error', {}))).toBeTruthy(); expect(isAxiosError(createError('error', {}, {} as any))).toBeTruthy();
}); });
}); });