UNPKG

bsl

Version:

基于React的框架和UI组件

106 lines (97 loc) 3.78 kB
import axios, { AxiosRequestConfig, Canceler, Method } from 'axios'; import * as React from 'react'; import RequestView from '../components/RequestView'; import BSL from '../typings'; type Omit_url = Omit<AxiosRequestConfig, 'url'>; type Omit_url_method = Omit<Omit_url, 'method'>; export interface Option extends Omit_url_method { /** 请求接口的名称 */ api: string; /** * app: 整个应用生命周期内缓存 * page: 页面生命周期内缓存 */ cache?: 'app' | 'page'; /** * @default 'GET' */ method?: Method; } export const cacheData: Map<string, any> = new Map(); function useRequest(): [(option: Option) => Promise<BSL.RequestResponse<any>>, React.MutableRefObject<Canceler | null>, (key: string) => void] { const clearCache = (key: string) => cacheData.delete(key); const cancelToken = React.useRef<(() => void) | null>(null); const request = (option: Option): Promise<BSL.RequestResponse<any>> => { return new Promise((resolve, reject) => { const { api } = option; const urlSearchParams = new URLSearchParams(); const createKey = () => JSON.stringify({ api: option.api, params: option.params, data: option.data }); const method = ((option.method || (axios.defaults.method)) || 'get').toLocaleUpperCase() as Method; const defualtData = RequestView.defaultData; const contentType = option.headers && option.headers['content-type'] || axios.defaults.headers['content-type']; const postData: Record<string, string | number | boolean | object> = {}; const isFormData = option.data && option.data instanceof FormData; const isDataArray = Array.isArray(option.data); // 判断是否有缓存 if (option.cache) { const key = createKey(); if (cacheData.has(key)) { resolve(cacheData.get(key)); return; } } if (defualtData && method === 'POST' && !isFormData && isDataArray === false) { Object.keys((defualtData)).forEach((key) => { urlSearchParams.append(key, defualtData[key]); postData[key] = defualtData[key]; }); } // 去除object中值为undefined的字段 if (option.data && !isFormData && isDataArray === false) { Object.keys((option.data)).forEach((key) => { if (option.data[key] !== undefined) { if (Array.isArray(option.data[key])) { urlSearchParams.append(key, JSON.stringify(option.data[key])); } else { urlSearchParams.append(key, option.data[key]); } postData[key] = option.data[key]; } }); } axios({ ...option, data: isFormData || isDataArray ? option.data : (contentType === 'application/json' ? postData : urlSearchParams), url: api, method, cancelToken: new axios.CancelToken((cancel) => { cancelToken.current = () => cancel('cancel'); }) }).then((res) => { if (res.status === 200) { let key: string | undefined ; // 判断接口是否需要缓存,并将结果储存起来 if (option.cache) { key = createKey(); cacheData.set(key, res.data); } resolve({ ...res.data, key }); } else { const response: BSL.RequestResponse<null> = { data: null, code: 500, msg: '网络错误' }; resolve(response); } }).catch((err) => { reject(err); }); }); }; return [request, cancelToken, clearCache]; } export default useRequest;