import { isFunction, isPlainObject } from '../helpers/isTypes'; import { transformURL } from '../helpers/transformURL'; import { AxiosRequestConfig, AxiosResponse, AxiosResponseError, } from '../core/Axios'; import { AxiosAdapterRequestConfig, AxiosAdapterResponse, AxiosAdapterResponseError, AxiosAdapterPlatformTask, AxiosAdapterRequestMethod, } from '../adpater/createAdapter'; import { isCancelToken } from './cancel'; import { AxiosErrorResponse, createError } from './createError'; import { generateType } from './generateType'; /** * 开始请求 * * 创建适配器配置并调用适配器,监听取消请求,注册监听回调,处理响应体和错误体,抛出异常。 * * @param config 请求配置 */ export function request(config: AxiosRequestConfig) { return new Promise((resolve, reject) => { const adapterConfig: AxiosAdapterRequestConfig = { ...(config as AxiosAdapterRequestConfig), type: generateType(config), url: transformURL(config), method: config.method!.toUpperCase() as AxiosAdapterRequestMethod, success, fail, }; let adapterTask: AxiosAdapterPlatformTask; try { adapterTask = config.adapter!(adapterConfig); } catch (err) { fail({ status: 400, statusText: 'Bad Adapter', }); console.error(err); } function success(baseResponse: AxiosAdapterResponse): void { const response = baseResponse as AxiosResponse; response.status = response.status ?? 200; response.statusText = response.statusText ?? 'OK'; response.headers = response.headers ?? {}; response.config = config; response.request = adapterTask; const { validateStatus } = config; if (!isFunction(validateStatus) || validateStatus(response.status)) { resolve(response); } else { catchError('validate status error', response); } } function fail(baseResponseError: AxiosAdapterResponseError): void { const responseError = baseResponseError as AxiosResponseError; responseError.isFail = true; responseError.status = responseError.status ?? 400; responseError.statusText = responseError.statusText ?? 'Fail'; responseError.headers = responseError.headers ?? {}; responseError.config = config; responseError.request = adapterTask; catchError('request fail', responseError); } function catchError( message: string, errorResponse: AxiosErrorResponse, ): void { reject(createError(message, config, errorResponse, adapterTask)); } if (isPlainObject(adapterTask)) { tryToggleProgressUpdate(adapterConfig, adapterTask.onProgressUpdate); } const { cancelToken } = config; if (isCancelToken(cancelToken)) { cancelToken.onCancel((reason) => { if (isPlainObject(adapterTask)) { tryToggleProgressUpdate(adapterConfig, adapterTask.offProgressUpdate); adapterTask?.abort?.(); } reject(reason); }); } }); } function tryToggleProgressUpdate( config: AxiosAdapterRequestConfig, progress?: (cb: (event: AnyObject) => void) => void, ) { const { type, onUploadProgress, onDownloadProgress } = config; if (isFunction(progress)) { switch (type) { case 'upload': if (isFunction(onUploadProgress)) { progress(onUploadProgress); } break; case 'download': if (isFunction(onDownloadProgress)) { progress(onDownloadProgress); } break; } } }