refactor: 拆分模块

pull/41/head
zjx0905 2023-03-28 21:32:54 +08:00
parent 0d1d21fc66
commit 879d08171d
21 changed files with 132 additions and 293 deletions

View File

@ -4,8 +4,8 @@ import {
isPlainObject, isPlainObject,
isString, isString,
isUndefined, isUndefined,
} from './helpers/is'; } from './helpers/isTypes';
import { assert, throwError } from './helpers/utils'; import { assert, throwError } from './helpers/error';
import { import {
AxiosProgressCallback, AxiosProgressCallback,
AxiosRequestFormData, AxiosRequestFormData,
@ -53,7 +53,11 @@ export interface AxiosAdapterRequestConfig extends AnyObject {
*/ */
method: AxiosAdapterRequestMethod; method: AxiosAdapterRequestMethod;
/** /**
* *
*/
params?: AnyObject;
/**
*
*/ */
data?: AnyObject; data?: AnyObject;
/** /**

View File

@ -7,7 +7,7 @@ import Axios, {
} from './core/Axios'; } from './core/Axios';
import { CancelToken, CancelTokenConstructor, isCancel } from './core/cancel'; import { CancelToken, CancelTokenConstructor, isCancel } from './core/cancel';
import { mergeConfig } from './core/mergeConfig'; import { mergeConfig } from './core/mergeConfig';
import { isString } from './helpers/is'; import { isString } from './helpers/isTypes';
import defaults from './defaults'; import defaults from './defaults';
export interface AxiosInstance extends Axios { export interface AxiosInstance extends Axios {
@ -19,7 +19,9 @@ export interface AxiosInstance extends Axios {
export interface AxiosStatic extends AxiosInstance { export interface AxiosStatic extends AxiosInstance {
Axios: AxiosConstructor; Axios: AxiosConstructor;
defaults: AxiosRequestConfig & { headers: Required<AxiosRequestHeaders> }; defaults: AxiosRequestConfig & {
headers: Required<AxiosRequestHeaders> & { common?: AnyObject };
};
CancelToken: CancelTokenConstructor; CancelToken: CancelTokenConstructor;
create(defaults?: AxiosRequestConfig): AxiosInstance; create(defaults?: AxiosRequestConfig): AxiosInstance;
createAdapter(platform: AxiosPlatform): AxiosAdapter; createAdapter(platform: AxiosPlatform): AxiosAdapter;

View File

@ -1,4 +1,4 @@
import { buildURL } from '../helpers/url'; import { buildURL } from '../helpers/buildURL';
import { mergeConfig } from './mergeConfig'; import { mergeConfig } from './mergeConfig';
import { import {
AxiosAdapter, AxiosAdapter,

View File

@ -1,4 +1,4 @@
import { isPlainObject } from '../helpers/is'; import { isPlainObject } from '../helpers/isTypes';
import { isCancel } from './cancel'; import { isCancel } from './cancel';
import { flattenHeaders } from './flattenHeaders'; import { flattenHeaders } from './flattenHeaders';
import { transformData } from './transformData'; import { transformData } from './transformData';

View File

@ -1,5 +1,5 @@
import { isPlainObject } from '../helpers/is'; import { isPlainObject } from '../helpers/isTypes';
import { omit } from '../helpers/utils'; import { omit } from '../helpers/omit';
import { AxiosRequestConfig, AxiosRequestHeaders } from './Axios'; import { AxiosRequestConfig, AxiosRequestHeaders } from './Axios';
export function flattenHeaders( export function flattenHeaders(

View File

@ -1,5 +1,5 @@
import { isUndefined, isPlainObject } from '../helpers/is'; import { isUndefined, isPlainObject } from '../helpers/isTypes';
import { deepMerge } from '../helpers/utils'; import { deepMerge } from '../helpers/deepMerge';
import { AxiosRequestConfig } from './Axios'; import { AxiosRequestConfig } from './Axios';
type AxiosRequestConfigKey = keyof AxiosRequestConfig; type AxiosRequestConfigKey = keyof AxiosRequestConfig;

View File

@ -1,5 +1,5 @@
import { isFunction, isPlainObject } from '../helpers/is'; import { isFunction, isPlainObject } from '../helpers/isTypes';
import { assert } from '../helpers/utils'; import { assert } from '../helpers/error';
import { import {
AxiosAdapterRequestConfig, AxiosAdapterRequestConfig,
AxiosAdapterRequestMethod, AxiosAdapterRequestMethod,
@ -19,16 +19,17 @@ function tryToggleProgressUpdate(
adapterConfig: AxiosAdapterRequestConfig, adapterConfig: AxiosAdapterRequestConfig,
progressUpdate?: (callback: AxiosProgressCallback) => void, progressUpdate?: (callback: AxiosProgressCallback) => void,
) { ) {
const { onUploadProgress, onDownloadProgress } = adapterConfig;
if (isFunction(progressUpdate)) { if (isFunction(progressUpdate)) {
switch (adapterConfig.type) { switch (adapterConfig.type) {
case 'upload': case 'upload':
if (isFunction(adapterConfig.onUploadProgress)) { if (isFunction(onUploadProgress)) {
progressUpdate(adapterConfig.onUploadProgress); progressUpdate(onUploadProgress);
} }
break; break;
case 'download': case 'download':
if (isFunction(adapterConfig.onDownloadProgress)) { if (isFunction(onDownloadProgress)) {
progressUpdate(adapterConfig.onDownloadProgress); progressUpdate(onDownloadProgress);
} }
break; break;
default: default:

View File

@ -1,4 +1,4 @@
import { isArray, isUndefined } from '../helpers/is'; import { isArray, isUndefined } from '../helpers/isTypes';
import { AxiosRequestFormData } from './Axios'; import { AxiosRequestFormData } from './Axios';
export interface AxiosTransformer { export interface AxiosTransformer {

View File

@ -1,18 +1,13 @@
import { import { buildURL } from '../helpers/buildURL';
buildURL, import { combineURL } from '../helpers/combineURL';
combineURL, import { dynamicInterpolation, isDynamicURL } from '../helpers/dynamicURL';
dynamicInterpolation, import { isAbsoluteURL } from '../helpers/isAbsoluteURL';
isAbsoluteURL,
isDynamicURL,
} from '../helpers/url';
import { AxiosRequestConfig } from './Axios'; import { AxiosRequestConfig } from './Axios';
export function transformURL(config: AxiosRequestConfig): string { export function transformURL(config: AxiosRequestConfig): string {
let url = config.url ?? ''; let url = config.url ?? '';
if (!isAbsoluteURL(url)) { if (!isAbsoluteURL(url)) url = combineURL(config.baseURL, url);
url = combineURL(config.baseURL, url);
}
if (isDynamicURL(url)) { if (isDynamicURL(url)) {
const sourceData = Object.assign({}, config.params, config.data); const sourceData = Object.assign({}, config.params, config.data);

View File

@ -1,15 +1,4 @@
import { isDate, isNull, isPlainObject, isUndefined } from './is'; import { isDate, isNull, isPlainObject, isUndefined } from './isTypes';
function encode(str: string): string {
return encodeURIComponent(str)
.replace(/%40/gi, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%20/g, '+')
.replace(/%5B/gi, '[')
.replace(/%5D/gi, ']');
}
export function buildURL( export function buildURL(
url = '', url = '',
@ -23,38 +12,6 @@ export function buildURL(
return generateURL(url, paramsSerializer(params)); return generateURL(url, paramsSerializer(params));
} }
const combineREG = /([^:])\/{2,}/g;
export function combineURL(baseURL = '', url: string): string {
const separator = '/';
const replaceStr = `$1${separator}`;
return `${baseURL}${separator}${url}`.replace(combineREG, replaceStr);
}
const dynamicREG = /\/?(:([a-zA-Z_$][\w-$]*))\/??/g;
export function dynamicInterpolation(
url: string,
sourceData?: unknown,
): string {
if (!isPlainObject(sourceData)) {
return url;
}
return url.replace(dynamicREG, ($1, $2, $3) =>
$1.replace($2, sourceData[$3]),
);
}
const absoluteREG = /^([a-z][a-z\d+\-.]*:)?\/\//i;
export function isAbsoluteURL(url: string): boolean {
return absoluteREG.test(url);
}
export function isDynamicURL(url: string): boolean {
dynamicREG.lastIndex = 0;
return dynamicREG.test(url);
}
function generateURL(url: string, serializedParams: string): string { function generateURL(url: string, serializedParams: string): string {
const hashIndex = url.indexOf('#'); const hashIndex = url.indexOf('#');
@ -106,3 +63,14 @@ function paramsSerialization(params?: AnyObject): string {
return parts.join('&'); return parts.join('&');
} }
function encode(str: string): string {
return encodeURIComponent(str)
.replace(/%40/gi, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%20/g, '+')
.replace(/%5B/gi, '[')
.replace(/%5D/gi, ']');
}

View File

@ -0,0 +1,7 @@
const combineREG = /([^:])\/{2,}/g;
export function combineURL(baseURL = '', url: string): string {
const separator = '/';
const replaceStr = `$1${separator}`;
return `${baseURL}${separator}${url}`.replace(combineREG, replaceStr);
}

22
src/helpers/deepMerge.ts Normal file
View File

@ -0,0 +1,22 @@
import { isPlainObject } from './isTypes';
export function deepMerge<T extends AnyObject>(...objs: T[]): T {
const result: AnyObject = {};
objs.forEach((obj: AnyObject) =>
Object.keys(obj).forEach((key) => {
const val = obj[key];
const resultVal = result[key];
if (isPlainObject(resultVal) && isPlainObject(val)) {
result[key] = deepMerge(resultVal, val);
} else if (isPlainObject(val)) {
result[key] = deepMerge(val);
} else {
result[key] = val;
}
}),
);
return result as T;
}

21
src/helpers/dynamicURL.ts Normal file
View File

@ -0,0 +1,21 @@
import { isPlainObject } from './isTypes';
const dynamicREG = /\/?(:([a-zA-Z_$][\w-$]*))\/??/g;
export function dynamicInterpolation(
url: string,
sourceData?: unknown,
): string {
if (!isPlainObject(sourceData)) {
return url;
}
return url.replace(dynamicREG, ($1, $2, $3) =>
$1.replace($2, sourceData[$3]),
);
}
export function isDynamicURL(url: string): boolean {
dynamicREG.lastIndex = 0;
return dynamicREG.test(url);
}

9
src/helpers/error.ts Normal file
View File

@ -0,0 +1,9 @@
export function assert(condition: boolean, msg: string) {
if (!condition) {
throwError(msg);
}
}
export function throwError(msg: string): void {
throw new Error(`[axios-miniprogram]: ${msg}`);
}

View File

@ -0,0 +1,4 @@
const absoluteREG = /^([a-z][a-z\d+\-.]*:)?\/\//i;
export function isAbsoluteURL(url: string): boolean {
return absoluteREG.test(url);
}

8
src/helpers/omit.ts Normal file
View File

@ -0,0 +1,8 @@
export function omit<T extends AnyObject, K extends keyof T>(
obj: T,
...keys: K[]
): Omit<T, K> {
const res = { ...obj };
keys.forEach((key: K) => delete res[key]);
return res;
}

View File

@ -1,54 +0,0 @@
import { isPlainObject } from './is';
export function deepMerge<T extends AnyObject>(...objs: T[]): T {
const result: AnyObject = {};
objs.forEach((obj: AnyObject) =>
Object.keys(obj).forEach((key) => {
const val = obj[key];
const resultVal = result[key];
if (isPlainObject(resultVal) && isPlainObject(val)) {
result[key] = deepMerge(resultVal, val);
} else if (isPlainObject(val)) {
result[key] = deepMerge(val);
} else {
result[key] = val;
}
}),
);
return result as T;
}
export function pick<T extends AnyObject, K extends keyof T>(
obj: T,
...keys: K[]
): Pick<T, K> {
const _pick: Partial<T> = {};
keys.forEach((key: K) => (_pick[key] = obj[key]));
return _pick as Pick<T, K>;
}
export function omit<T extends AnyObject, K extends keyof T>(
obj: T,
...keys: K[]
): Omit<T, K> {
const _omit = Object.assign({}, obj);
keys.forEach((key: K) => delete _omit[key]);
return _omit;
}
export function assert(condition: boolean, msg: string) {
if (!condition) {
throwError(msg);
}
}
export function throwError(msg: string): void {
throw new Error(`[axios-miniprogram]: ${msg}`);
}

View File

@ -0,0 +1,19 @@
import { describe, test, expect } from 'vitest';
import { assert, throwError } from '../../src/helpers/error';
describe('测试 src/helpers/error.ts', () => {
test('第一个参数为 true 时应该无事发生', () => {
expect(assert(true, '')).toBeUndefined();
});
test('第一个参数为 false 时应该抛出异常', () => {
expect(() => assert(false, '')).toThrowError();
});
test('应该抛出异常', () => {
expect(() => throwError('')).toThrowError('[axios-miniprogram]: ');
expect(() => throwError('error')).toThrowError(
'[axios-miniprogram]: error',
);
});
});

View File

@ -1,117 +0,0 @@
import { describe, test, expect } from 'vitest';
import {
isArray,
isDate,
isEmptyArray,
isEmptyObject,
isFunction,
isNull,
isPlainObject,
isString,
isUndefined,
} from '../../src/helpers/is';
describe('对 src/helpers/is.ts 进行测试', () => {
test('传入数组应该返回 true其他参数应该返回 fasle', () => {
expect(isArray([0])).toBe(true);
expect(isArray([])).toBe(true);
expect(isArray({})).toBe(false);
expect(isArray(0)).toBe(false);
expect(isArray('')).toBe(false);
expect(isArray(undefined)).toBe(false);
expect(isArray(null)).toBe(false);
});
test('传入 Date 实例应该返回 true其他参数应该返回 fasle', () => {
expect(isDate(new Date())).toBe(true);
expect(isDate({})).toBe(false);
expect(isDate([])).toBe(false);
expect(isDate(0)).toBe(false);
expect(isDate('')).toBe(false);
expect(isDate(undefined)).toBe(false);
expect(isDate(null)).toBe(false);
});
test('传入空数组应该返回 true其他参数应该返回 fasle', () => {
expect(isEmptyArray([])).toBe(true);
expect(isEmptyArray([0])).toBe(false);
expect(isEmptyArray({})).toBe(false);
expect(isEmptyArray(0)).toBe(false);
expect(isEmptyArray('')).toBe(false);
expect(isEmptyArray(undefined)).toBe(false);
expect(isEmptyArray(null)).toBe(false);
});
test('传入空对象应该返回 true其他参数应该返回 fasle', () => {
expect(isEmptyObject({})).toBe(true);
expect(isEmptyObject({ a: 0 })).toBe(false);
expect(isEmptyObject([0])).toBe(false);
expect(isEmptyObject([])).toBe(false);
expect(isEmptyObject(0)).toBe(false);
expect(isEmptyObject('')).toBe(false);
expect(isEmptyObject(undefined)).toBe(false);
expect(isEmptyObject(null)).toBe(false);
});
test('传入空函数应该返回 true其他参数应该返回 fasle', () => {
expect(
isFunction(() => {
return;
}),
).toBe(true);
expect(
isFunction(function () {
return;
}),
).toBe(true);
expect(isFunction({})).toBe(false);
expect(isFunction([])).toBe(false);
expect(isFunction(0)).toBe(false);
expect(isFunction('')).toBe(false);
expect(isFunction(undefined)).toBe(false);
expect(isFunction(null)).toBe(false);
});
test('传入空 null 应该返回 true其他参数应该返回 fasle', () => {
expect(isNull(null)).toBe(true);
expect(isNull({ a: 0 })).toBe(false);
expect(isNull([0])).toBe(false);
expect(isNull([])).toBe(false);
expect(isNull(0)).toBe(false);
expect(isNull('')).toBe(false);
expect(isNull(undefined)).toBe(false);
});
test('传入普通对象应该返回 true其他参数应该返回 fasle', () => {
expect(isPlainObject({})).toBe(true);
expect(isPlainObject({ a: 0 })).toBe(true);
expect(isPlainObject([0])).toBe(false);
expect(isPlainObject([])).toBe(false);
expect(isPlainObject(0)).toBe(false);
expect(isPlainObject('')).toBe(false);
expect(isPlainObject(undefined)).toBe(false);
expect(isPlainObject(null)).toBe(false);
});
test('传入字符串应该返回 true其他参数应该返回 fasle', () => {
expect(isString('')).toBe(true);
expect(isString({})).toBe(false);
expect(isString({ a: 0 })).toBe(false);
expect(isString([0])).toBe(false);
expect(isString([])).toBe(false);
expect(isString(0)).toBe(false);
expect(isString(undefined)).toBe(false);
expect(isString(null)).toBe(false);
});
test('传入 undefined 应该返回 true其他参数应该返回 fasle', () => {
expect(isUndefined(undefined)).toBe(true);
expect(isUndefined('')).toBe(false);
expect(isUndefined({})).toBe(false);
expect(isUndefined({ a: 0 })).toBe(false);
expect(isUndefined([0])).toBe(false);
expect(isUndefined([])).toBe(false);
expect(isUndefined(0)).toBe(false);
expect(isUndefined(null)).toBe(false);
});
});

View File

@ -1,50 +0,0 @@
import { describe, test, expect } from 'vitest';
import {
assert,
deepMerge,
omit,
pick,
throwError,
} from '../../src/helpers/utils';
describe('对 src/helpers/utils.ts 进行测试', () => {
test('测试 assert() 是否符合预期', () => {
expect(assert(true, '')).toBeUndefined();
expect(() => assert(false, '')).toThrow();
expect(() => assert(false, 'msg')).toThrowError('[axios-miniprogram]: msg');
});
test('测试 deepMerge() 是否符合预期', () => {
expect(deepMerge({})).toEqual({});
expect(deepMerge({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 });
expect(deepMerge({ a: { a: 1 } }, { a: { b: 2 } })).toEqual({
a: { a: 1, b: 2 },
});
expect(deepMerge({ a: { a: 1, b: 1 } }, { a: { a: 2, b: 2 } })).toEqual({
a: { a: 2, b: 2 },
});
expect(deepMerge({ a: { a: 1 } }, { a: 2 })).toEqual({
a: 2,
});
});
test('测试 omit() 是否符合预期', () => {
expect(omit({})).toEqual({});
expect(omit({ a: 1, b: 1 }, 'a')).toEqual({ b: 1 });
expect(omit({ a: 1, b: 1 }, 'a', 'b')).toEqual({});
});
test('测试 pick() 是否符合预期', () => {
expect(pick({})).toEqual({});
expect(pick({ a: 1, b: 1 }, 'a')).toEqual({ a: 1 });
expect(pick({ a: 1, b: 1 }, 'a', 'b')).toEqual({ a: 1, b: 1 });
});
test('测试 throwError() 是否符合预期', () => {
expect(() => throwError('')).toThrowError('[axios-miniprogram]: ');
expect(() => throwError('msg')).toThrowError('[axios-miniprogram]: msg');
expect(() => throwError(' msg ')).toThrowError(
'[axios-miniprogram]: msg ',
);
});
});