From 74856f7fdef4f0e75b8665300960416a840f561c Mon Sep 17 00:00:00 2001 From: zjx0905 <954270063@qq.com> Date: Thu, 4 May 2023 16:26:59 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20axios.use=20=E5=87=BD=E6=95=B0=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E5=80=BC=E4=B8=8D=E6=98=AF=E5=BD=93=E5=89=8D=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/Axios.ts | 838 +++++++++++++++++----------------- src/core/MiddlewareManager.ts | 121 +++-- 2 files changed, 480 insertions(+), 479 deletions(-) diff --git a/src/core/Axios.ts b/src/core/Axios.ts index 2ab521e..e996e9e 100644 --- a/src/core/Axios.ts +++ b/src/core/Axios.ts @@ -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 - > { - /** - * 请求适配器 - */ - 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; - /** - * 转换响应数据 - */ - transformResponse?: AxiosTransformer; - /** - * 错误处理 - */ - errorHandler?: (error: unknown) => Promise; - /** - * 监听下载进度 - */ - onDownloadProgress?: AxiosUploadProgressCallback; - /** - * 监听上传进度 - */ - onUploadProgress?: AxiosUploadProgressCallback; + extends Partial< + Omit + > { + /** + * 请求适配器 + */ + 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 + /** + * 转换响应数据 + */ + transformResponse?: AxiosTransformer + /** + * 错误处理 + */ + errorHandler?: (error: unknown) => Promise + /** + * 监听下载进度 + */ + 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 { - (config: AxiosRequestConfig): Promise< - AxiosResponse - >; - ( - url: string, - config?: AxiosRequestConfig, - ): Promise>; + (config: AxiosRequestConfig): Promise< + AxiosResponse + > + ( + url: string, + config?: AxiosRequestConfig, + ): Promise> } /** * 普通的请求方法 */ export type AxiosRequestMethodFn = ( - url: string, - config?: AxiosRequestConfig, -) => Promise>; + url: string, + config?: AxiosRequestConfig, +) => Promise> /** * 带参数的请求方法 */ export type AxiosRequestMethodFnWithParams = ( - url: string, - params?: AnyObject, - config?: AxiosRequestConfig, -) => Promise>; + url: string, + params?: AnyObject, + config?: AxiosRequestConfig, +) => Promise> /** * 带数据的请求方法 */ export type AxiosRequestMethodFnWithData = ( - url: string, - data?: AxiosRequestData, - config?: AxiosRequestConfig, -) => Promise>; + url: string, + data?: AxiosRequestData, + config?: AxiosRequestConfig, +) => Promise> export interface AxiosDomainRequestHandler { - (config: AxiosRequestConfig): Promise; + (config: AxiosRequestConfig): Promise } /** * 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(), - /** - * 响应拦截器 - */ - response: new InterceptorManager(), - }; + /** + * 拦截器 + */ + interceptors = { + /** + * 请求拦截器 + */ + request: new InterceptorManager(), + /** + * 响应拦截器 + */ + response: new InterceptorManager(), + } - /** - * 中间件 - */ - #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> + | Partial> + )[] = [] - const requestHandler = { - resolved: this.#handleRequest, - }; - const errorHandler = { - rejected: config.errorHandler, - }; - const chain: ( - | Partial> - | Partial> - )[] = []; + 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 + } - return chain.reduce( - (next, { resolved, rejected }) => - next.then( - // @ts-ignore - resolved, - rejected, - ), - Promise.resolve(config), - ) as Promise; - }; + #eachRequestInterceptors(executor: InterceptorExecutor) { + this.interceptors.request.forEach(executor) + if (this.#parent) { + this.#parent.#eachRequestInterceptors(executor) + } + } - #eachRequestInterceptors(executor: InterceptorExecutor) { - this.interceptors.request.forEach(executor); - if (this.#parent) { - this.#parent.#eachRequestInterceptors(executor); - } - } + #eachResponseInterceptors(executor: InterceptorExecutor) { + this.interceptors.response.forEach(executor) + if (this.#parent) { + this.#parent.#eachResponseInterceptors(executor) + } + } - #eachResponseInterceptors(executor: InterceptorExecutor) { - 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 => { - if (!this.#parent) { - return this.#middleware.run(ctx, respond); - } - return this.#middleware.enhanceRun(this.#parent.#run)(ctx, respond); - }; + #run = ( + ctx: MiddlewareContext, + respond: MiddlewareCallback, + ): Promise => { + 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) + } } diff --git a/src/core/MiddlewareManager.ts b/src/core/MiddlewareManager.ts index 9140aa0..77f1218 100644 --- a/src/core/MiddlewareManager.ts +++ b/src/core/MiddlewareManager.ts @@ -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; + (): Promise } /** * 中间件上下文 */ export interface MiddlewareContext { - /** - * 请求体 - * - * 同于请求配置 - */ - req: AxiosRequestConfig; - /** - * 响应体 - */ - res: null | AxiosResponse; + /** + * 请求体 + * + * 同于请求配置 + */ + req: AxiosRequestConfig + /** + * 响应体 + */ + res: null | AxiosResponse } /** * 中间件 */ export interface MiddlewareCallback { - (ctx: MiddlewareContext, next: MiddlewareNext): Promise; + (ctx: MiddlewareContext, next: MiddlewareNext): Promise } /** * 中间件管理器 */ 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)) + } + } }