feat: 修改 mergeConfig 中 data 的合并方式

pull/41/head
zjx0905 2023-04-08 22:37:50 +08:00
parent ff3f50a580
commit ee6a31b4bb
6 changed files with 83 additions and 80 deletions

View File

@ -253,9 +253,9 @@ export function createAdapter(platform: AxiosPlatform): AxiosAdapter {
function transformResult(result: AnyObject): void {
result.status =
result.status ?? result.statusCode ?? isUndefined(result.data)
? 400
: 200;
result.status ??
result.statusCode ??
(isUndefined(result.data) ? 400 : 200);
result.statusText =
result.status === 200
? 'OK'

View File

@ -1,14 +1,13 @@
import { isString } from './helpers/isTypes';
import { AxiosDomainRequest } from './core/AxiosDomain';
import Axios, {
AxiosConstructor,
AxiosRequestConfig,
AxiosRequestHeaders,
AxiosResponse,
} from './core/Axios';
import { CancelToken, CancelTokenConstructor, isCancel } from './core/cancel';
import { isAxiosError } from './core/createError';
import { mergeConfig } from './core/mergeConfig';
import { AxiosAdapter, createAdapter, AxiosPlatform } from './adapter';
import { createAdapter } from './adapter';
import defaults from './defaults';
export interface AxiosInstanceDefaults extends AxiosRequestConfig {
@ -18,27 +17,11 @@ export interface AxiosInstanceDefaults extends AxiosRequestConfig {
headers: Required<AxiosRequestHeaders>;
}
export interface AxiosInstance extends Axios {
export interface AxiosInstance extends AxiosDomainRequest, Axios {
/**
*
*/
defaults: AxiosInstanceDefaults;
<TData = unknown>(
/**
*
*/
config: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
<TData = unknown>(
/**
*
*/
url: string,
/**
*
*/
config?: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
}
export interface AxiosStatic extends AxiosInstance {
@ -61,7 +44,7 @@ export interface AxiosStatic extends AxiosInstance {
*
* @param platform
*/
createAdapter(platform: AxiosPlatform): AxiosAdapter;
createAdapter: typeof createAdapter;
/**
* Cancel
*/
@ -72,40 +55,26 @@ export interface AxiosStatic extends AxiosInstance {
isAxiosError: typeof isAxiosError;
}
function createInstance(defaults: AxiosRequestConfig): AxiosInstance {
const instance = new Axios(defaults);
function createInstance(defaults: AxiosRequestConfig) {
const context = new Axios(defaults);
const instance = context.request as AxiosInstance;
function axios<TData = unknown>(
urlOrConfig: string | AxiosRequestConfig,
config: AxiosRequestConfig = {},
): Promise<AxiosResponse<TData>> {
if (isString(urlOrConfig)) {
config.url = urlOrConfig;
} else {
config = urlOrConfig;
}
Object.assign(instance, context, {
// instance.fork 内部调用了 context 的私有方法
// 所以直接调用 instance.fork 会导致程序会抛出无法访问私有方法的异常
// instance.fork 调用时 this 重新指向 context解决此问题
fork: context.fork.bind(context),
});
Object.setPrototypeOf(instance, Object.getPrototypeOf(context));
return instance.request(config);
}
Object.assign(axios, instance);
Object.setPrototypeOf(
axios,
Object.assign(Object.getPrototypeOf(instance), {
// axios.fork 内部调用了 instance 的私有方法,但是无法直接访问私有方法程序抛出导致异常
// axios.fork 调用时 this 重新指向 instance解决此问题
fork: instance.fork.bind(instance),
}),
);
return axios as AxiosInstance;
return instance;
}
const axios = createInstance(defaults) as AxiosStatic;
axios.Axios = Axios;
axios.CancelToken = CancelToken;
axios.create = function create(defaults: AxiosRequestConfig): AxiosInstance {
axios.create = function create(defaults) {
return createInstance(mergeConfig(axios.defaults, defaults));
};
axios.createAdapter = createAdapter;

View File

@ -207,9 +207,7 @@ export default class Axios extends AxiosDomain {
};
constructor(defaults: AxiosRequestConfig = {}) {
super(defaults, (...args) => {
return this.#processRequest(...args);
});
super(defaults, (config) => this.#processRequest(config));
}
getUri(config: AxiosRequestConfig): string {
@ -228,9 +226,11 @@ export default class Axios extends AxiosDomain {
if (!isAbsoluteURL(baseURL)) {
defaults.baseURL = combineURL(this.defaults.baseURL ?? '', baseURL);
}
return new AxiosDomain(mergeConfig(this.defaults, defaults), (...args) => {
return this.#processRequest(...args);
});
return new AxiosDomain(
mergeConfig(this.defaults, defaults),
(config) => this.#processRequest(config),
);
}
#processRequest<TData = unknown>(config: AxiosRequestConfig) {

View File

@ -1,3 +1,4 @@
import { isString, isUndefined } from '../helpers/isTypes';
import { deepMerge } from '../helpers/deepMerge';
import { mergeConfig } from './mergeConfig';
import { AxiosRequestConfig, AxiosRequestData, AxiosResponse } from './Axios';
@ -9,6 +10,16 @@ export interface AxiosDomainRequest {
*/
config: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
<TData = unknown>(
/**
*
*/
url: string,
/**
*
*/
config?: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
}
export interface AxiosDomainAsRequest {
@ -126,10 +137,24 @@ export default class AxiosDomain {
constructor(
defaults: AxiosRequestConfig = {},
processRequest: AxiosDomainRequest,
processRequest: (config: AxiosRequestConfig) => Promise<AxiosResponse>,
) {
this.defaults = defaults;
this.request = (config) => {
this.request = (
urlOrConfig: string | AxiosRequestConfig,
config: AxiosRequestConfig = {},
) => {
if (isString(urlOrConfig)) {
config.url = urlOrConfig;
} else {
config = urlOrConfig;
}
if (isUndefined(config.method)) {
config.method = 'get';
}
return processRequest(mergeConfig(this.defaults, config));
};
@ -141,10 +166,8 @@ export default class AxiosDomain {
#createAsRequests() {
for (const alias of AxiosDomain.as) {
this[alias] = function processAsRequest(url, config = {}) {
config.url = url;
config.method = alias;
return this.request(config);
return this.request(url, config);
};
}
}
@ -152,11 +175,9 @@ export default class AxiosDomain {
#createAspRequests() {
for (const alias of AxiosDomain.asp) {
this[alias] = function processAspRequest(url, params = {}, config = {}) {
config.url = url;
config.method = alias;
config.params = deepMerge(params, config.params ?? {});
return this.request(config);
return this.request(url, config);
};
}
}
@ -164,11 +185,9 @@ export default class AxiosDomain {
#createAsdRequests() {
for (const alias of AxiosDomain.asd) {
this[alias] = function processAsdRequest(url, data = {}, config = {}) {
config.url = url;
config.method = alias;
config.data = deepMerge(data, config.data ?? {});
return this.request(config);
return this.request(url, config);
};
}
}

View File

@ -5,13 +5,13 @@ import { AxiosRequestConfig } from './Axios';
const fromConfig2Map: Record<string, boolean> = {
url: true,
method: true,
data: true,
upload: true,
download: true,
};
const deepMergeConfigMap: Record<string, boolean> = {
headers: true,
params: true,
data: true,
};
export function mergeConfig(

View File

@ -13,14 +13,12 @@ describe('src/core/mergeConfig.ts', () => {
const c1 = {
url: 'a',
method: 'get' as const,
data: {},
upload: true,
download: true,
};
const c2 = {
url: 'b',
method: 'post' as const,
data: {},
upload: false,
download: false,
};
@ -37,6 +35,27 @@ describe('src/core/mergeConfig.ts', () => {
});
test('应该深度合并', () => {
const o1 = {
v1: 1,
v2: 1,
v3: {
v1: 1,
},
};
const o2 = {
v2: 2,
v3: {
v2: 2,
},
};
const o3 = {
v1: 1,
v2: 2,
v3: {
v1: 1,
v2: 2,
},
};
const c1 = {
headers: {
common: {
@ -44,9 +63,8 @@ describe('src/core/mergeConfig.ts', () => {
},
v1: 1,
},
params: {
v1: 1,
},
params: o1,
data: o1,
};
const c2 = {
headers: {
@ -55,9 +73,8 @@ describe('src/core/mergeConfig.ts', () => {
},
v2: 2,
},
params: {
v2: 2,
},
params: o2,
data: o2,
};
const mc = {
headers: {
@ -68,10 +85,8 @@ describe('src/core/mergeConfig.ts', () => {
v1: 1,
v2: 2,
},
params: {
v1: 1,
v2: 2,
},
params: o3,
data: o3,
};
expect(mergeConfig(c1, {})).toEqual(c1);