fix: axios.use 函数返回值不是当前实例

pull/49/head
zjx0905 2023-05-04 16:26:59 +08:00
parent fa5979b17e
commit 74856f7fde
2 changed files with 480 additions and 479 deletions

View File

@ -1,559 +1,561 @@
import {
PLAIN_METHODS,
WITH_DATA_METHODS,
WITH_PARAMS_METHODS,
} from '../constants/methods';
import { isString } from '../helpers/isTypes';
import { dispatchRequest } from '../request/dispatchRequest';
import { CancelToken } from '../request/cancel';
import { AxiosTransformer } from '../request/transformData';
import { deepMerge } from '../helpers/deepMerge';
PLAIN_METHODS,
WITH_DATA_METHODS,
WITH_PARAMS_METHODS,
} from '../constants/methods'
import { isString } from '../helpers/isTypes'
import { dispatchRequest } from '../request/dispatchRequest'
import { CancelToken } from '../request/cancel'
import { AxiosTransformer } from '../request/transformData'
import { deepMerge } from '../helpers/deepMerge'
import {
AxiosAdapter,
AxiosAdapterRequestMethod,
AxiosAdapterPlatformTask,
AxiosAdapterRequestConfig,
AxiosAdapterResponseData,
} from '../adpater/createAdapter';
AxiosAdapter,
AxiosAdapterRequestMethod,
AxiosAdapterPlatformTask,
AxiosAdapterRequestConfig,
AxiosAdapterResponseData,
} from '../adpater/createAdapter'
import InterceptorManager, {
Interceptor,
InterceptorExecutor,
} from './InterceptorManager';
Interceptor,
InterceptorExecutor,
} from './InterceptorManager'
import MiddlewareManager, {
MiddlewareCallback,
MiddlewareContext,
} from './MiddlewareManager';
import { mergeConfig } from './mergeConfig';
MiddlewareCallback,
MiddlewareContext,
} from './MiddlewareManager'
import { mergeConfig } from './mergeConfig'
/**
*
*/
export type AxiosRequestMethod =
| AxiosAdapterRequestMethod
| 'options'
| 'get'
| 'head'
| 'post'
| 'put'
| 'patch'
| 'delete'
| 'trace'
| 'connect';
| AxiosAdapterRequestMethod
| 'options'
| 'get'
| 'head'
| 'post'
| 'put'
| 'patch'
| 'delete'
| 'trace'
| 'connect'
/**
*
*/
export interface AxiosRequestHeaders extends AnyObject {
/**
*
*/
common?: AnyObject;
/**
* options
*/
options?: AnyObject;
/**
* get
*/
get?: AnyObject;
/**
* head
*/
head?: AnyObject;
/**
* post
*/
post?: AnyObject;
/**
* put
*/
put?: AnyObject;
/**
* delete
*/
delete?: AnyObject;
/**
* trace
*/
trace?: AnyObject;
/**
* connect
*/
connect?: AnyObject;
/**
*
*/
common?: AnyObject
/**
* options
*/
options?: AnyObject
/**
* get
*/
get?: AnyObject
/**
* head
*/
head?: AnyObject
/**
* post
*/
post?: AnyObject
/**
* put
*/
put?: AnyObject
/**
* delete
*/
delete?: AnyObject
/**
* trace
*/
trace?: AnyObject
/**
* connect
*/
connect?: AnyObject
}
/**
*
*/
export interface AxiosRequestFormData extends AnyObject {
/**
*
*/
name: string;
/**
*
*/
filePath: string;
/**
*
*/
name: string
/**
*
*/
filePath: string
}
/**
*
*/
export type AxiosRequestData =
| string
| AnyObject
| ArrayBuffer
| AxiosRequestFormData;
| string
| AnyObject
| ArrayBuffer
| AxiosRequestFormData
/**
*
*/
export type AxiosResponseData = number | AxiosAdapterResponseData;
export type AxiosResponseData = number | AxiosAdapterResponseData
/**
*
*/
export interface AxiosProgressEvent extends AnyObject {
/**
*
*/
progress: number;
/**
*
*/
progress: number
}
/**
*
*/
export interface AxiosDownloadProgressEvent extends AxiosProgressEvent {
/**
* Bytes
*/
totalBytesWritten: number;
/**
* Bytes
*/
totalBytesExpectedToWrite: number;
/**
* Bytes
*/
totalBytesWritten: number
/**
* Bytes
*/
totalBytesExpectedToWrite: number
}
/**
*
*/
export interface AxiosDownloadProgressCallback {
(event: AxiosDownloadProgressEvent): void;
(event: AxiosDownloadProgressEvent): void
}
/**
*
*/
export interface AxiosUploadProgressEvent extends AxiosProgressEvent {
/**
* Bytes
*/
totalBytesSent: number;
/**
* Bytes
*/
totalBytesExpectedToSend: number;
/**
* Bytes
*/
totalBytesSent: number
/**
* Bytes
*/
totalBytesExpectedToSend: number
}
/**
*
*/
export interface AxiosUploadProgressCallback {
(event: AxiosUploadProgressEvent): void;
(event: AxiosUploadProgressEvent): void
}
/**
*
*/
export interface AxiosRequestConfig
extends Partial<
Omit<AxiosAdapterRequestConfig, 'type' | 'success' | 'fail'>
> {
/**
*
*/
adapter?: AxiosAdapter;
/**
*
*/
baseURL?: string;
/**
* URL
*/
url?: string;
/**
*
*/
params?: AnyObject;
/**
*
*/
data?: AxiosRequestData;
/**
*
*/
headers?: AxiosRequestHeaders;
/**
*
*/
method?: AxiosRequestMethod;
/**
*
*/
cancelToken?: CancelToken;
/**
*
*/
download?: boolean;
/**
*
*/
upload?: boolean;
/**
*
*/
paramsSerializer?: (params?: AnyObject) => string;
/**
*
*/
validateStatus?: (status: number) => boolean;
/**
*
*/
transformRequest?: AxiosTransformer<AxiosRequestData>;
/**
*
*/
transformResponse?: AxiosTransformer<AxiosResponseData>;
/**
*
*/
errorHandler?: (error: unknown) => Promise<AxiosResponse>;
/**
*
*/
onDownloadProgress?: AxiosUploadProgressCallback;
/**
*
*/
onUploadProgress?: AxiosUploadProgressCallback;
extends Partial<
Omit<AxiosAdapterRequestConfig, 'type' | 'success' | 'fail'>
> {
/**
*
*/
adapter?: AxiosAdapter
/**
*
*/
baseURL?: string
/**
* URL
*/
url?: string
/**
*
*/
params?: AnyObject
/**
*
*/
data?: AxiosRequestData
/**
*
*/
headers?: AxiosRequestHeaders
/**
*
*/
method?: AxiosRequestMethod
/**
*
*/
cancelToken?: CancelToken
/**
*
*/
download?: boolean
/**
*
*/
upload?: boolean
/**
*
*/
paramsSerializer?: (params?: AnyObject) => string
/**
*
*/
validateStatus?: (status: number) => boolean
/**
*
*/
transformRequest?: AxiosTransformer<AxiosRequestData>
/**
*
*/
transformResponse?: AxiosTransformer<AxiosResponseData>
/**
*
*/
errorHandler?: (error: unknown) => Promise<AxiosResponse>
/**
*
*/
onDownloadProgress?: AxiosUploadProgressCallback
/**
*
*/
onUploadProgress?: AxiosUploadProgressCallback
}
/**
*
*/
export interface AxiosResponse<
TData extends AxiosResponseData = AxiosResponseData,
TData extends AxiosResponseData = AxiosResponseData,
> extends AnyObject {
/**
*
*/
status: number;
/**
*
*/
statusText: string;
/**
*
*/
headers: AnyObject;
/**
*
*/
data: TData;
/**
*
*/
config: AxiosRequestConfig;
/**
*
*/
request?: AxiosAdapterPlatformTask;
/**
*
*/
status: number
/**
*
*/
statusText: string
/**
*
*/
headers: AnyObject
/**
*
*/
data: TData
/**
*
*/
config: AxiosRequestConfig
/**
*
*/
request?: AxiosAdapterPlatformTask
}
/**
*
*/
export interface AxiosResponseError extends AnyObject {
/**
*
*/
status: number;
/**
*
*/
statusText: string;
/**
*
*/
headers: AnyObject;
/**
*
*/
data: AnyObject;
/**
*
*/
isFail: true;
/**
*
*/
config: AxiosRequestConfig;
/**
*
*/
request?: AxiosAdapterPlatformTask;
/**
*
*/
status: number
/**
*
*/
statusText: string
/**
*
*/
headers: AnyObject
/**
*
*/
data: AnyObject
/**
*
*/
isFail: true
/**
*
*/
config: AxiosRequestConfig
/**
*
*/
request?: AxiosAdapterPlatformTask
}
export interface AxiosRequest {
<TData extends AxiosResponseData>(config: AxiosRequestConfig): Promise<
AxiosResponse<TData>
>;
<TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
<TData extends AxiosResponseData>(config: AxiosRequestConfig): Promise<
AxiosResponse<TData>
>
<TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>
}
/**
*
*/
export type AxiosRequestMethodFn = <TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
url: string,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>
/**
*
*/
export type AxiosRequestMethodFnWithParams = <TData extends AxiosResponseData>(
url: string,
params?: AnyObject,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
url: string,
params?: AnyObject,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>
/**
*
*/
export type AxiosRequestMethodFnWithData = <TData extends AxiosResponseData>(
url: string,
data?: AxiosRequestData,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
url: string,
data?: AxiosRequestData,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>
export interface AxiosDomainRequestHandler {
(config: AxiosRequestConfig): Promise<AxiosResponse>;
(config: AxiosRequestConfig): Promise<AxiosResponse>
}
/**
* Axios
*/
export interface AxiosConstructor {
new (config: AxiosRequestConfig): Axios;
new (config: AxiosRequestConfig): Axios
}
export default class Axios {
/**
*
*/
#parent?: Axios;
/**
*
*/
#parent?: Axios
/**
*
*/
defaults: AxiosRequestConfig;
/**
*
*/
defaults: AxiosRequestConfig
/**
*
*/
interceptors = {
/**
*
*/
request: new InterceptorManager<AxiosRequestConfig>(),
/**
*
*/
response: new InterceptorManager<AxiosResponse>(),
};
/**
*
*/
interceptors = {
/**
*
*/
request: new InterceptorManager<AxiosRequestConfig>(),
/**
*
*/
response: new InterceptorManager<AxiosResponse>(),
}
/**
*
*/
#middleware = new MiddlewareManager();
/**
*
*/
#middleware = new MiddlewareManager()
/**
* options
*/
options!: AxiosRequestMethodFn;
/**
* options
*/
options!: AxiosRequestMethodFn
/**
* get
*/
get!: AxiosRequestMethodFnWithParams;
/**
* get
*/
get!: AxiosRequestMethodFnWithParams
/**
* head
*/
head!: AxiosRequestMethodFnWithParams;
/**
* head
*/
head!: AxiosRequestMethodFnWithParams
/**
* post
*/
post!: AxiosRequestMethodFnWithData;
/**
* post
*/
post!: AxiosRequestMethodFnWithData
/**
* put
*/
put!: AxiosRequestMethodFnWithData;
/**
* put
*/
put!: AxiosRequestMethodFnWithData
/**
* patch
*/
patch!: AxiosRequestMethodFnWithData;
/**
* patch
*/
patch!: AxiosRequestMethodFnWithData
/**
* delete
*/
delete!: AxiosRequestMethodFnWithParams;
/**
* delete
*/
delete!: AxiosRequestMethodFnWithParams
/**
* trace
*/
trace!: AxiosRequestMethodFn;
/**
* trace
*/
trace!: AxiosRequestMethodFn
/**
* connect
*/
connect!: AxiosRequestMethodFn;
/**
* connect
*/
connect!: AxiosRequestMethodFn
/**
*
*
* @param middleware
*/
use: (middleware: MiddlewareCallback) => MiddlewareManager;
/**
*
* @param config
* @param parent
*/
constructor(config: AxiosRequestConfig, parent?: Axios) {
this.defaults = config
this.#parent = parent
}
/**
*
* @param config
* @param parent
*/
constructor(config: AxiosRequestConfig, parent?: Axios) {
this.defaults = config;
this.#parent = parent;
this.use = this.#middleware.use;
}
/**
*
*/
request: AxiosRequest = (
urlOrConfig: string | AxiosRequestConfig,
config: AxiosRequestConfig = {},
) => {
if (isString(urlOrConfig)) {
config.url = urlOrConfig
} else {
config = urlOrConfig
}
config = mergeConfig(this.defaults, config)
config.method = (config.method?.toLowerCase() ??
'get') as AxiosRequestMethod
/**
*
*/
request: AxiosRequest = (
urlOrConfig: string | AxiosRequestConfig,
config: AxiosRequestConfig = {},
) => {
if (isString(urlOrConfig)) {
config.url = urlOrConfig;
} else {
config = urlOrConfig;
}
config = mergeConfig(this.defaults, config);
config.method = (config.method?.toLowerCase() ??
'get') as AxiosRequestMethod;
const requestHandler = {
resolved: this.#handleRequest,
}
const errorHandler = {
rejected: config.errorHandler,
}
const chain: (
| Partial<Interceptor<AxiosRequestConfig>>
| Partial<Interceptor<AxiosResponse>>
)[] = []
const requestHandler = {
resolved: this.#handleRequest,
};
const errorHandler = {
rejected: config.errorHandler,
};
const chain: (
| Partial<Interceptor<AxiosRequestConfig>>
| Partial<Interceptor<AxiosResponse>>
)[] = [];
this.#eachRequestInterceptors((requestInterceptor) => {
chain.unshift(requestInterceptor)
})
chain.push(requestHandler)
this.#eachResponseInterceptors((responseInterceptor) => {
chain.push(responseInterceptor)
})
chain.push(errorHandler)
this.#eachRequestInterceptors((requestInterceptor) => {
chain.unshift(requestInterceptor);
});
chain.push(requestHandler);
this.#eachResponseInterceptors((responseInterceptor) => {
chain.push(responseInterceptor);
});
chain.push(errorHandler);
return chain.reduce(
(next, { resolved, rejected }) =>
next.then(
// @ts-ignore
resolved,
rejected,
),
Promise.resolve(config),
) as Promise<AxiosResponse>
}
return chain.reduce(
(next, { resolved, rejected }) =>
next.then(
// @ts-ignore
resolved,
rejected,
),
Promise.resolve(config),
) as Promise<AxiosResponse>;
};
#eachRequestInterceptors(executor: InterceptorExecutor<AxiosRequestConfig>) {
this.interceptors.request.forEach(executor)
if (this.#parent) {
this.#parent.#eachRequestInterceptors(executor)
}
}
#eachRequestInterceptors(executor: InterceptorExecutor<AxiosRequestConfig>) {
this.interceptors.request.forEach(executor);
if (this.#parent) {
this.#parent.#eachRequestInterceptors(executor);
}
}
#eachResponseInterceptors(executor: InterceptorExecutor<AxiosResponse>) {
this.interceptors.response.forEach(executor)
if (this.#parent) {
this.#parent.#eachResponseInterceptors(executor)
}
}
#eachResponseInterceptors(executor: InterceptorExecutor<AxiosResponse>) {
this.interceptors.response.forEach(executor);
if (this.#parent) {
this.#parent.#eachResponseInterceptors(executor);
}
}
/**
*
*
* @param middleware
*/
use = (middleware: MiddlewareCallback) => {
this.#middleware.use(middleware)
return this
}
#handleRequest = async (config: AxiosRequestConfig) => {
const ctx = this.#middleware.createContext(config);
await this.#run(ctx, this.#handleResponse);
return ctx.res as AxiosResponse;
};
#handleRequest = async (config: AxiosRequestConfig) => {
const ctx = this.#middleware.createContext(config)
await this.#run(ctx, this.#handleResponse)
return ctx.res as AxiosResponse
}
#handleResponse = async (ctx: MiddlewareContext) => {
ctx.res = await dispatchRequest(ctx.req);
};
#handleResponse = async (ctx: MiddlewareContext) => {
ctx.res = await dispatchRequest(ctx.req)
}
#run = (
ctx: MiddlewareContext,
respond: MiddlewareCallback,
): Promise<void> => {
if (!this.#parent) {
return this.#middleware.run(ctx, respond);
}
return this.#middleware.enhanceRun(this.#parent.#run)(ctx, respond);
};
#run = (
ctx: MiddlewareContext,
respond: MiddlewareCallback,
): Promise<void> => {
if (!this.#parent) {
return this.#middleware.run(ctx, respond)
}
return this.#middleware.enhanceRun(this.#parent.#run)(ctx, respond)
}
}
for (const method of PLAIN_METHODS) {
Axios.prototype[method] = function processRequestMethod(url, config = {}) {
config.method = method;
return this.request(url, config);
};
Axios.prototype[method] = function processRequestMethod(url, config = {}) {
config.method = method
return this.request(url, config)
}
}
for (const method of WITH_PARAMS_METHODS) {
Axios.prototype[method] = function processRequestMethodWithParams(
url,
params = {},
config = {},
) {
config.method = method;
config.params = deepMerge(params, config.params ?? {});
return this.request(url, config);
};
Axios.prototype[method] = function processRequestMethodWithParams(
url,
params = {},
config = {},
) {
config.method = method
config.params = deepMerge(params, config.params ?? {})
return this.request(url, config)
}
}
for (const method of WITH_DATA_METHODS) {
Axios.prototype[method] = function processRequestMethodWithData(
url,
data,
config = {},
) {
config.method = method;
config.data = data;
return this.request(url, config);
};
Axios.prototype[method] = function processRequestMethodWithData(
url,
data,
config = {},
) {
config.method = method
config.data = data
return this.request(url, config)
}
}

View File

@ -1,86 +1,85 @@
import { assert } from '../helpers/error';
import { isFunction } from '../helpers/isTypes';
import { AxiosRequestConfig, AxiosResponse } from './Axios';
import { assert } from '../helpers/error'
import { isFunction } from '../helpers/isTypes'
import { AxiosRequestConfig, AxiosResponse } from './Axios'
export interface MiddlewareNext {
(): Promise<void>;
(): Promise<void>
}
/**
*
*/
export interface MiddlewareContext {
/**
*
*
*
*/
req: AxiosRequestConfig;
/**
*
*/
res: null | AxiosResponse;
/**
*
*
*
*/
req: AxiosRequestConfig
/**
*
*/
res: null | AxiosResponse
}
/**
*
*/
export interface MiddlewareCallback {
(ctx: MiddlewareContext, next: MiddlewareNext): Promise<void>;
(ctx: MiddlewareContext, next: MiddlewareNext): Promise<void>
}
/**
*
*/
export default class MiddlewareManager {
/**
*
*/
#middlewares: MiddlewareCallback[] = [];
/**
*
*/
#middlewares: MiddlewareCallback[] = []
/**
*
*
* @param middleware
*/
use = (middleware: MiddlewareCallback) => {
assert(isFunction(middleware), 'middleware 不是一个 function');
this.#middlewares.push(middleware);
return this;
};
/**
*
*
* @param middleware
*/
use(middleware: MiddlewareCallback) {
assert(isFunction(middleware), 'middleware 不是一个 function')
this.#middlewares.push(middleware)
}
/**
*
*/
createContext(config: AxiosRequestConfig): MiddlewareContext {
return {
req: config,
res: null,
};
}
/**
*
*/
createContext(config: AxiosRequestConfig): MiddlewareContext {
return {
req: config,
res: null,
}
}
/**
*
*
* @param ctx
* @param respond
*/
run(ctx: MiddlewareContext, respond: MiddlewareCallback) {
const middlewares = [...this.#middlewares, respond];
async function next() {
await middlewares.shift()!(ctx, next);
}
return next();
}
/**
*
*
* @param ctx
* @param respond
*/
run(ctx: MiddlewareContext, respond: MiddlewareCallback) {
const middlewares = [...this.#middlewares, respond]
async function next() {
await middlewares.shift()!(ctx, next)
}
return next()
}
/**
*
*
* @param enhancer
*/
enhanceRun(enhancer: MiddlewareManager['run']): MiddlewareManager['run'] {
return (ctx, respond) => {
return enhancer(ctx, () => this.run(ctx, respond));
};
}
/**
*
*
* @param enhancer
*/
enhanceRun(enhancer: MiddlewareManager['run']): MiddlewareManager['run'] {
return (ctx, respond) => {
return enhancer(ctx, () => this.run(ctx, respond))
}
}
}