UNPKG

@magic_npm/simple-tools

Version:

`simple-tools` is a simple set of tools

1 lines 12 kB
{"version":3,"file":"index.cjs","sources":["../../../src/utils/useData.ts","../../../src/utils/useApi.ts"],"sourcesContent":["import type { UseDataModel } from './types'\n\n/**\n * 数据声明hook\n * @param func - 返回初始数据的函数\n * @returns [数据模型, 数据更新函数]\n */\nconst useData: UseDataModel = function (func) {\n const model = func()\n return [\n model,\n /**\n * 合并数据,数据初始化的合并\n * @param coverData - 需要合并的数据\n * @param isReset - 是否重置性合并\n * @returns 合并后的数据\n */\n (coverData, isReset) => {\n // 待合并的数据\n const cover = (isReset || !coverData) ? useData.mergeData(func(), coverData) : coverData\n // 合并到数据模型上\n return useData.mergeData(model, cover)\n }\n ]\n}\n\n/**\n * 获取数据类型\n * @param data - 需要检测的数据\n * @returns 数据类型字符串 ('null' | 'undefined' | 'object' | 'array' | 'number' | 'string' | 'set')\n */\nuseData.getDataType = function (data) {\n return Object.prototype.toString.call(data).slice(8, -1).toLowerCase()\n}\n\n/**\n * 合并数据,只有类型相同的数据才会被合并\n * @param data - 原始数据\n * @param cover - 需要合并的数据\n * @returns 合并后的数据\n */\nuseData.mergeData = function (data, cover) {\n if (data && useData.getDataType(data) === 'object' && ['object', 'undefined'].includes(useData.getDataType(cover))) {\n cover && Object.keys(data).forEach((k) => {\n if (k in cover) {\n (data as any)[k] = cover[k]\n }\n })\n }\n return data\n}\n\nexport default useData","/**\n * 用于接口请求,规范代码结构\n * \n * @param api - 接口方法\n * @param options - 配置选项\n * @returns [apiFunc, loading, apiObj]\n * \n * @example\n * const [apiFunc, loading, apiObj] = useApi(api, {\n * isCancel: true, // 连续请求,是否只响应最后一个请求结果\n * isRepeat: true, // 是否可重复请求/提交\n * isSingle: false, // 是否开启单例模式\n * loading: {}, // 定义 loading 状态\n * params: () => ({}), // 预设接口参数\n * before: (params) => true, // 请求前处理\n * outputModel: (params) => params, // 输出数据处理\n * inputModel: (res) => res, // 输入数据处理\n * success: (data, loadingKey, res) => {}, // 成功回调\n * error: (err) => {}, // 失败回调\n * loadingStart: (params, loadingKey) => {}, // loading开始回调\n * loadingEnd: (loadingState) => {} // loading结束回调\n * });\n */\nimport useData from './useData'\nimport type { useApiFuncModel, useApiOptionsModel, useApiObjStatusModel } from './types'\n\nexport default function useApi<\n Q extends object, // 基础参数类型\n OQ extends object | void, // outputModel 方法处理后参数类型\n R extends object | unknown | void, // 接口返回值类型\n RD extends object | void, // inputModel 返回值处理后结果类型\n L extends object | undefined, // loading 对象类型\n LK extends keyof L, // loading 对象键名类型\n LS // loadingStart 方法返回值类型\n>(\n api: (arg?: OQ, opt?: any) => Promise<R>,\n options?: useApiOptionsModel<R, RD, Q, OQ, L, LK, LS>\n): [useApiFuncModel<R, RD, Q, LK>, L, useApiObjStatusModel<R, RD, LK, Q, OQ>] {\n const {\n isCancel,\n isRepeat,\n isSingle,\n loading,\n params,\n loadingStart,\n loadingEnd,\n before,\n success,\n error,\n inputModel,\n outputModel\n } = {\n isCancel: true,\n isRepeat: true,\n isSingle: false,\n ...options\n }\n\n const apiObj: useApiObjStatusModel<R, RD, LK, Q, OQ> = {\n status: 0, // Api请求的状态,0 待请求, 1 请求中, 2 成功, 3 失败\n sendNum: {}, // 根据 loadingKey 来记录请求次数\n sendLatestKey: undefined, // 最新请求的 loadingKey\n pm: undefined, // 最新一次请求结果\n err: '', // 请求错误结果记录\n params: undefined, // 请求参数记录\n output: undefined, // 输出参数数据记录\n result: {\n res: undefined as R, // 未处理前的数据\n data: undefined as RD, // 经过 inputModel 处理后的结果\n loadingKey: '' as LK // loading键名\n },\n\n /**\n * 关闭正在请求的Api\n */\n cancelApi: async () => {\n const cancel = apiObj.pm?.cancel\n const pm = Promise.resolve()\n\n if (cancel) {\n cancel?.()\n apiObj.status = 0\n\n try {\n await apiObj.pm\n } catch (err) { }\n\n console.log('[cancel successful]')\n } else {\n console.log('[cancel error] find not cancel function.')\n }\n\n return pm\n }\n }\n\n /**\n * 调用API函数\n * @param query - 接口请求参数\n * @param loadingKey - 指定响应对应的loading键名\n */\n const apiFunc: useApiFuncModel<R, RD, Q, LK> = async (query, loadingKey = 'value' as LK) => {\n // 用来建立连接 loadingStart loadingEnd\n let loadingState = undefined as LS\n const sameSend: { [key in LK]?: number } = {}\n\n try {\n // 设置请求参数\n apiObj.params = params?.()\n apiObj.params && useData.mergeData(apiObj.params, query)\n\n // 请求前处理\n if (typeof before === 'function') {\n let bPm = before(apiObj.params && JSON.parse(JSON.stringify(apiObj.params)))\n\n if (bPm === false) {\n throw 'close send api.'\n }\n\n if (bPm instanceof Promise) {\n await bPm\n }\n }\n\n // 禁止重复请求处理\n if (!isRepeat && apiObj.status === 1) {\n return Promise.reject('操作频繁,请稍后再试')\n }\n\n // 是否单例模式\n if (isSingle && apiObj.status === 2) {\n success?.(apiObj.result.data, apiObj.result.loadingKey, apiObj.result.res)\n return Promise.resolve(apiObj.result)\n }\n\n // 输出给外部的参数数据\n apiObj.output = typeof outputModel === 'function'\n ? outputModel(apiObj.params && JSON.parse(JSON.stringify(apiObj.params)))\n : apiObj.params && JSON.parse(JSON.stringify(apiObj.params))\n\n // 连续请求模式,关闭上一次正在请求的此接口\n if (isCancel && isRepeat && apiObj.status === 1) {\n await apiObj.cancelApi()\n }\n\n // 取反 (相同 loadingKey 重复请求,上一个请求未完成)\n if (!(apiObj.sendLatestKey === loadingKey && apiObj.status === 1)) {\n // loading 处理\n if (loading && loadingKey && loadingKey in loading) {\n (loading as any)[loadingKey] = true\n }\n\n // loadingStart 回调\n if (loadingStart) {\n loadingStart(\n apiObj.params && JSON.parse(JSON.stringify(apiObj.params)),\n loadingKey\n )\n }\n }\n\n // 根据 loadingKey 分别记录请求次数\n if (loadingKey) {\n const k = loadingKey\n apiObj.sendNum[k] = (apiObj.sendNum[k] || 0) + 1\n sameSend[k] = apiObj.sendNum[k]\n }\n\n apiObj.sendLatestKey = loadingKey\n apiObj.status = 1\n\n // 调用 api\n apiObj.pm = api(apiObj.output)\n const res = await apiObj.pm\n\n apiObj.status = 2\n apiObj.result.res = res\n apiObj.result.loadingKey = loadingKey\n if (typeof inputModel === 'function') {\n apiObj.result.data = inputModel?.(res)\n }\n\n // 成功回调处理\n success?.(apiObj.result.data, loadingKey, apiObj.result.res)\n } catch (err: any) {\n // 失败处理\n apiObj.status = 3\n apiObj.err = err\n error?.(apiObj.err)\n }\n\n // 1. 最新请求的 loadingKey 与上一次不一样 || 2. 相同 loadingKey 的请求次数一致\n // 备注:条件1 不一致则直接处理loading关闭;条件2 请求次数一致则表示没有重复的请求\n const slk = apiObj.sendLatestKey\n\n if (apiObj.sendLatestKey != loadingKey || (slk && sameSend[slk] === apiObj.sendNum[slk])) {\n // loading 处理\n if (loading && loadingKey && loadingKey in loading) {\n (loading as any)[loadingKey] = false\n }\n\n // loadingEnd 处理\n loadingEnd?.(loadingState)\n }\n\n // 返回处理\n return new Promise((resolve, reject) => {\n if (apiObj.status === 2) {\n resolve(apiObj.result)\n } else if (apiObj.status === 3) {\n reject(apiObj.err)\n } else {\n reject(new Error('useApi exception'))\n }\n })\n }\n\n return [apiFunc, loading as L, { ...apiObj }]\n}"],"names":["useData","func","model","coverData","isReset","cover","mergeData","getDataType","data","Object","prototype","toString","call","slice","toLowerCase","includes","keys","forEach","k","api","options","isCancel","isRepeat","isSingle","loading","params","loadingStart","loadingEnd","before","success","error","inputModel","outputModel","apiObj","status","sendNum","sendLatestKey","pm","err","output","result","res","loadingKey","cancelApi","async","cancel","_a","Promise","resolve","console","log","query","loadingState","sameSend","bPm","JSON","parse","stringify","reject","slk","Error"],"mappings":"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"}