UNPKG

@shencom/request

Version:

封装 axios 请求,兼容了 uni-app 的 uni.request 和 uni.uploadFile 的适配器

153 lines (123 loc) 4.39 kB
import type { AxiosAdapter, AxiosRequestConfig } from 'axios'; import axios from 'axios'; // @ts-expect-error 没有声明文件 import settle from 'axios/unsafe/core/settle.js'; type GeneralCallbackResultCustom = UniApp.GeneralCallbackResult & { data?: unknown; statusCode?: number; header?: unknown; }; function isFileType(files: any[]) { return files.some((file) => file.name && file.file); } function isMultiUpload(config: Record<string, any>) { return Array.isArray(config.files) && config.files.length > 0; } const isObject = (data: any) => Object.prototype.toString.call(data) === '[object Object]'; const isAliFormData = (data: any) => isObject(data) && 'appendData' in data && 'realFormData' in data; const isFormData = (data: unknown): data is FormData => Object.prototype.toString.call(data) === '[object FormData]' || isAliFormData(data); function isUploadFile(config: Record<string, any>) { if (isFormData(config.data)) return true; if (config.method === 'post') { if (config.data) { const data = JSON.parse(config.data); if (data.file?.path) return true; if (data.filePath) return true; if (isMultiUpload(data) && isFileType(data.files)) return true; } } return false; } interface Config extends AxiosRequestConfig { formData?: FormData; header?: AxiosRequestConfig['headers']; complete?: (response: UniApp.RequestSuccessCallbackResult & UniApp.GeneralCallbackResult) => void; } function format(config: Config, resolve: (value: unknown) => void, reject: (reason?: any) => void) { const uniConfig = { ...config, url: axios.getUri(config), header: { ...config.headers }, } as Config & UniApp.UploadFileOption; delete uniConfig.headers; if (isUploadFile(uniConfig)) { delete uniConfig.header?.['Content-Type']; // Let the browser set it if (typeof uniConfig.data === 'string') { const data = JSON.parse(uniConfig.data); uniConfig.formData = {}; Object.keys(data).forEach((name) => { const value = data[name]; if (name === 'file') { uniConfig.filePath = value?.path; return; } if (name === 'filePath') uniConfig.filePath = value as string; uniConfig.formData[name] = value; }); uniConfig.name = 'file'; delete uniConfig.data; } } else if (uniConfig.method?.toLocaleUpperCase() === 'GET') { // 兼容 get 时的 params 字段 uniConfig.data = uniConfig.data ? uniConfig.data : uniConfig.params; } uniConfig.complete = function (response: GeneralCallbackResultCustom) { const result = { data: response.data, status: response.statusCode, statusText: response.errMsg, headers: response.header, config: uniConfig, }; settle(resolve, reject, result); }; return uniConfig; } function uniappAdapter(config: AxiosRequestConfig = {}) { return new Promise((resolve, reject) => { const uniConfig = format(config, resolve, reject); let requestTask: UniApp.RequestTask | null; if (config.cancelToken) { config.cancelToken.promise.then((cancel) => { if (!requestTask) return; requestTask.abort(); reject(cancel); // 取消请求 requestTask = null; }); } if (isUploadFile(config)) { if (typeof FormData === 'undefined') { requestTask = uni.uploadFile(uniConfig) as unknown as UniApp.RequestTask; } else { // uniapp H5 环境下,使用 uni.uploadFile 发送请求,不返回响应头 // 需要使用 axios 发送请求 const controller = new AbortController(); delete uniConfig.header; axios .request({ ...uniConfig, headers: config.headers, signal: controller.signal, // @ts-expect-error uniapp 的 H5 环境下需要移除适配器 adapter: null, }) .then((res) => { settle(resolve, reject, res); }) .catch((err) => { settle(resolve, reject, err); }); requestTask = controller as unknown as UniApp.UploadTask; } } else { requestTask = uni.request( uniConfig as UniApp.RequestOptions, ) as unknown as UniApp.RequestTask; } }); } const adapter = uniappAdapter as AxiosAdapter; export { adapter };