UNPKG

@shencom/request

Version:

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

146 lines (120 loc) 3.94 kB
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; import axios from 'axios'; import { pickBy } from 'lodash-es'; declare module 'axios' { interface AxiosRequestConfig { isFilterEmpty?: boolean; errcode?: string; } } type Dictionary<T = any> = Record<string, T>; export type Platforms = true | 'weixin' | 'ali' | 'h5' | 'app'; export interface ScHeaders extends Dictionary { scid: string; Authorization?: string | null; miniProgram: Platforms; } export interface ScResponse<T> { data: T; errcode: string; errmsg: string; } export interface Config<D = Dictionary> extends AxiosRequestConfig<D> { headers?: Partial<ScHeaders>; } export type ScRequest = <R = Dictionary, D = Dictionary, CustomRes = false>( url: string, data?: D, config?: Config<D>, ) => Promise<CustomRes extends true ? R : ScResponse<R>>; export interface CustomAxiosInstance extends Omit<AxiosInstance, 'post' | 'get'> { post: ScRequest; get: ScRequest; upload: typeof __upload; } const instance = axios.create() as unknown as CustomAxiosInstance; instance.defaults.errcode = '0000'; instance.defaults.isFilterEmpty = true; instance.defaults.timeout = 20000; const isObject = (data: any) => Object.prototype.toString.call(data) === '[object Object]'; function handledBodyEmpty(data: any | any[]) { if (!data) return {}; if (Array.isArray(data)) { return data.map((item) => { if (isObject(item)) return pickBy(item, (v) => v !== null && v !== undefined && v !== ''); return item; }); } if (isObject(data)) { return pickBy(data, (v) => v !== ''); } return data; } function checkFilterEmpty(config: AxiosRequestConfig<any | any[]>) { if (['POST', 'GET'].includes(config.method?.toLocaleUpperCase() || '')) { config.data = handledBodyEmpty(config.data); } if (config.method?.toLocaleUpperCase() === 'GET') { if (config.params) config.params = handledBodyEmpty(config.params); } return config; } const __base = <R = Dictionary>(url: string, config: AxiosRequestConfig) => { let { isFilterEmpty = true } = instance.defaults; if (typeof config?.isFilterEmpty === 'boolean') { isFilterEmpty = config.isFilterEmpty; } if (isFilterEmpty) config = checkFilterEmpty(config); const errcode = config?.errcode ?? instance.defaults.errcode; return new Promise<R>((resolve, reject) => { instance .request({ url, ...config }) .then((res) => { if (res.data.errcode) { if (res.data?.errcode === errcode) { resolve(res.data); return; } reject(res); } else { resolve(res.data); } }) .catch(reject); }); }; const __post: ScRequest = (url, data, config) => { return __base(url, { data, ...config, method: 'post' }); }; const __get: ScRequest = (url, data, config) => { return __base(url, { params: data, ...config, method: 'get' }); }; const __upload = <R = Dictionary, D = Dictionary, CustomRes = false>( url: string, data: D, config?: Config<D>, ): Promise<CustomRes extends true ? AxiosResponse<R, D> : ScResponse<R>> => { return new Promise((resolve, reject) => { instance .request({ url, data, ...config, method: 'post' }) .then((res) => { if (res.status === 200) { // oss 直传情况下,返回的是空字符串 if (typeof res.data === 'string' && res.data === '') { // oss 成功请求后不返回数据 // 需要从 Headers 中获取 Etag 数据,所以不进行数据过滤 resolve(res as any); } else if (res.data?.errcode === res.config?.errcode) { resolve(res.data); } else { reject(res); } } else reject(res); }) .catch(reject); }); }; instance.post = __post; instance.get = __get; instance.upload = __upload; export { instance };