import { buildURL } from '../helpers/buildURL'; import { isAbsoluteURL } from '../helpers/isAbsoluteURL'; import { combineURL } from '../helpers/combineURL'; import { isFunction, isPromise, isString } from '../helpers/isTypes'; import { AxiosAdapter, AxiosAdapterRequestMethod, AxiosAdapterTask, AxiosAdapterRequestConfig, AxiosAdapterResponseData, } from '../adapter'; import InterceptorManager, { Interceptor } from './InterceptorManager'; import { mergeConfig } from './mergeConfig'; import { CancelToken } from './cancel'; import { dispatchRequest } from './dispatchRequest'; import { AxiosTransformer } from './transformData'; import AxiosDomain from './AxiosDomain'; export type AxiosRequestMethod = | 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; } export interface AxiosRequestFormData extends AnyObject { /** * 文件名 */ name: string; /** * 文件路径 */ filePath: string; } export type AxiosRequestData = AnyObject | AxiosRequestFormData; export type AxiosResponseData = undefined | number | AxiosAdapterResponseData; export interface AxiosProgressEvent { /** * 下载进度 */ progress: number; /** * 已经下载的数据长度 */ totalBytesSent: number; /** * 预期需要下载的数据总长度 */ totalBytesExpectedToSend: number; } export interface AxiosProgressCallback { (event: AxiosProgressEvent): void; } export interface AxiosRequestConfig extends Partial< Omit > { /** * 请求适配器 */ adapter?: AxiosAdapter; /** * 基础路径 */ baseURL?: string; /** * 请求的 URL */ url?: string; /** * 请求参数 */ params?: AnyObject; /** * 请求数据 */ data?: AxiosRequestData; /** * 请求头 */ headers?: AxiosRequestHeaders; /** * 请求方法 */ method?: AxiosRequestMethod; /** * 取消令牌 */ cancelToken?: CancelToken; /** * 上传 */ upload?: boolean; /** * 下载 */ download?: boolean; /** * 转换请求数据 */ transformRequest?: AxiosTransformer; /** * 转换响应数据 */ transformResponse?: AxiosTransformer; /** * 错误处理 */ errorHandler?: (error: unknown) => Promise | void; /** * 监听上传进度 */ onUploadProgress?: AxiosProgressCallback; /** * 监听下载进度 */ onDownloadProgress?: AxiosProgressCallback; /** * 请求参数系列化函数 */ paramsSerializer?: (params?: AnyObject) => string; /** * 校验状态码 */ validateStatus?: (status: number) => boolean; } export interface AxiosResponse< TData extends AxiosResponseData = AxiosResponseData, > extends AnyObject { /** * 状态码 */ status: number; /** * 状态字符 */ statusText: string; /** * 响应头 */ headers: AnyObject; /** * 响应数据 */ data: TData; /** * 请求配置 */ config: AxiosRequestConfig; /** * 请求任务 */ request?: AxiosAdapterTask; } export interface AxiosResponseError extends AnyObject { /** * 状态码 */ status: number; /** * 状态字符 */ statusText: string; /** * 响应头 */ headers: AnyObject; /** * 错误数据 */ data?: AnyObject; /** * 失败的请求,指没能够成功响应的请求 */ isFail: true; /** * 请求配置 */ config: AxiosRequestConfig; /** * 请求任务 */ request?: AxiosAdapterTask; } export interface AxiosConstructor { new (config: AxiosRequestConfig): Axios; } export default class Axios extends AxiosDomain { /** * 拦截器 */ interceptors = { /** * 请求拦截器 */ request: new InterceptorManager(), /** * 响应拦截器 */ response: new InterceptorManager(), }; constructor(defaults: AxiosRequestConfig = {}) { super(defaults, (config) => this.#processRequest(config)); } getUri(config: AxiosRequestConfig): string { const { url, params, paramsSerializer } = mergeConfig( this.defaults, config, ); return buildURL(url, params, paramsSerializer).replace(/^\?/, ''); } /** * 派生领域 */ fork = (defaults: AxiosRequestConfig = {}) => { if (isString(defaults.baseURL) && !isAbsoluteURL(defaults.baseURL)) { defaults.baseURL = combineURL(this.defaults.baseURL, defaults.baseURL); } return new AxiosDomain(mergeConfig(this.defaults, defaults), (config) => this.#processRequest(config), ); }; #processRequest(config: AxiosRequestConfig) { const chain: [ Interceptor | Interceptor, ] = [ { resolved: dispatchRequest, }, ]; this.interceptors.request.forEach(chain.unshift.bind(chain)); this.interceptors.response.forEach(chain.push.bind(chain)); let next = Promise.resolve(config); for (const { resolved, rejected } of chain) { next = next.then( // @ts-ignore resolved, rejected, ); } // 错误处理 next = next.catch((reason) => { const { errorHandler } = config; if (isFunction(errorHandler)) { const promise = errorHandler(reason); if (isPromise(promise)) { return promise.then(() => Promise.reject(reason)); } } return Promise.reject(reason); }); return next as Promise; } }