UNPKG

rc-hooks

Version:
212 lines (211 loc) 11.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearCache = void 0; var tslib_1 = require("tslib"); var react_1 = require("react"); var ut2_1 = require("ut2"); var usePersistFn_1 = tslib_1.__importDefault(require("../usePersistFn")); var useUpdateEffect_1 = tslib_1.__importDefault(require("../useUpdateEffect")); var useLatest_1 = tslib_1.__importDefault(require("../useLatest")); var useUnmountedRef_1 = tslib_1.__importDefault(require("../useUnmountedRef")); var Async_1 = tslib_1.__importStar(require("./Async")); Object.defineProperty(exports, "clearCache", { enumerable: true, get: function () { return Async_1.clearCache; } }); /** * 管理异步函数。 * * @param {Function} asyncFn 异步函数。 * @param {Object} [options] 配置项。 * @param {boolean} [options.autoRun=true] 在初始化时自动执行异步函数。如果设置为 `false`,则需要手动调用 `run` 触发执行。默认 `true`。 * @param {*} [options.initialData] 初始化的 `data`。 * @param {boolean} [options.defaultLoading=false] 初始化默认 `loading` 值。默认值等于 `autoRun && !loadingDelay`。 * @param {Array} [options.defaultParams] 如果 `autoRun=true` 自动执行 `run` 的默认参数。 * @param {Array} [options.refreshDeps] 在 `autoRun = true` 时,`refreshDeps` 变化,会触发重新执行。 * @param {Function} [options.onBefore] 异步函数执行前触发,参数为 `params`。 * @param {Function} [options.onSuccess] 异步函数 `resolve` 时触发,参数为 `data` 和 `params`。 * @param {Function} [options.onError] 异步函数报错时触发,参数为 `error` 和 `params`。 * @param {string} [options.cacheKey] 缓存的键值。启用缓存机制,异步成功结果将被缓存。如果多个相同 cacheKey 的异步同时触发中,将共享第一个异步结果。 * @param {number} [options.cacheTime=5*60*1000] 缓存时间。单位毫秒。 * @param {boolean} [options.persisted=false] 持久化数据。当有缓存数据时,不再执行异步函数。需要配合 `cacheKey` `cacheTime` 使用。默认 `false`。 * @param {number} [options.loadingDelay] 设置 `loading` 延迟时间,避免闪烁,单位为毫秒。 * @param {number} [options.pollingInterval] 轮询间隔,单位为毫秒。设置后,将进入轮询模式,定时触发 `run`。 * @param {boolean} [options.pollingWhenHidden=true] 在页面隐藏时,是否继续轮询。如果为 `true`,不会停止轮询。如果为 `false`,在页面隐藏时会暂时停止轮询,页面重新显示时继续上次轮询。默认 `true`。 * @param {boolean} [options.refreshOnWindowFocus=false] 在屏幕重新获取焦点或重新显示时,是否重新发起请求。如果为 `false`,不会重新发起请求。如果为 `true`,在屏幕重新聚焦或重新显示时,会重新发起请求。默认 `false`。 * @param {number} [options.focusTimespan=5000] 屏幕重新聚焦,重新发起请求时间间隔。需要配置 `refreshOnWindowFocus` 使用。默认 `5000`。 * @param {number} [options.debounceInterval] 防抖间隔,单位为毫秒,设置后,请求进入防抖模式。 * @param {number} [options.throttleInterval] 节流间隔,单位为毫秒,设置后,请求进入节流模式。 * @returns {Object} * @example * const { data, error, loading, run, cancel, refresh, mutate } = useAsync(asyncFn, options); */ var useAsync = function (asyncFn, options) { var _a = options || {}, _b = _a.autoRun, autoRun = _b === void 0 ? true : _b, _c = _a.refreshDeps, refreshDeps = _c === void 0 ? [] : _c, defaultParams = _a.defaultParams, loadingDelay = _a.loadingDelay, __INTERNAL_FORMAT__ = _a.__INTERNAL_FORMAT__, defaultLoading = _a.defaultLoading, initialData = _a.initialData, _d = _a.cacheKey, cacheKey = _d === void 0 ? '' : _d, _e = _a.cacheTime, cacheTime = _e === void 0 ? 5 * 60 * 1000 : _e, _f = _a.persisted, persisted = _f === void 0 ? false : _f, _g = _a.onSuccess, onSuccess = _g === void 0 ? ut2_1.noop : _g, _h = _a.onError, onError = _h === void 0 ? ut2_1.noop : _h, _j = _a.onFinally, onFinally = _j === void 0 ? ut2_1.noop : _j, _k = _a.onBefore, onBefore = _k === void 0 ? ut2_1.noop : _k, _l = _a.pollingInterval, pollingInterval = _l === void 0 ? 0 : _l, _m = _a.pollingWhenHidden, pollingWhenHidden = _m === void 0 ? true : _m, _o = _a.refreshOnWindowFocus, refreshOnWindowFocus = _o === void 0 ? false : _o, _p = _a.focusTimespan, focusTimespan = _p === void 0 ? 5000 : _p, debounceInterval = _a.debounceInterval, throttleInterval = _a.throttleInterval; var _q = tslib_1.__read((0, react_1.useState)(function () { return ({ // 参数兼容非array的情况 params: [], loading: !!((0, ut2_1.isUndefined)(defaultLoading) ? autoRun && !loadingDelay : defaultLoading), error: null, data: cacheKey ? (0, Async_1.getCache)(cacheKey) : initialData }); }), 2), state = _q[0], set = _q[1]; var latestState = (0, useLatest_1.default)(state); var unmountedRef = (0, useUnmountedRef_1.default)(); var loadingDelayTimerRef = (0, react_1.useRef)(null); // 延迟loading // 持久化一些函数 var asyncFnPersist = (0, usePersistFn_1.default)(asyncFn); var onSuccessPersist = (0, usePersistFn_1.default)(onSuccess); var onErrorPersist = (0, usePersistFn_1.default)(onError); var onFinallyPersist = (0, usePersistFn_1.default)(onFinally); var onBeforePersist = (0, usePersistFn_1.default)(onBefore); var internalFormatRef = (0, useLatest_1.default)(__INTERNAL_FORMAT__); // 异步执行前 var handleBefore = (0, react_1.useCallback)(function (p) { onBeforePersist(p); // 取消延迟loading if (loadingDelayTimerRef.current) { clearTimeout(loadingDelayTimerRef.current); } // 缓存数据 var cacheData = cacheKey ? (0, Async_1.getCache)(cacheKey) : undefined; // 没有缓存数据 或 没有开启持久缓存,设置loading if (!cacheData || !persisted) { if (latestState.current.loading !== !loadingDelay || !(0, ut2_1.equalArrayLike)(latestState.current.params, p)) { set(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { loading: !loadingDelay, params: p })); }); } // 设置延迟loading定时器 if (loadingDelay) { loadingDelayTimerRef.current = setTimeout(function () { if (!unmountedRef.current) { set(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { loading: true })); }); } }, loadingDelay); } } }, [cacheKey, latestState, loadingDelay, onBeforePersist, persisted, unmountedRef]); // 异步执行成功后 var handleSuccess = (0, react_1.useCallback)(function (res, args) { if (loadingDelayTimerRef.current) { clearTimeout(loadingDelayTimerRef.current); } set(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { data: res, error: null, loading: false })); }); onSuccessPersist(res, args); }, [onSuccessPersist]); // 异步执行失败后 var handleError = (0, react_1.useCallback)(function (err, args) { if (loadingDelayTimerRef.current) { clearTimeout(loadingDelayTimerRef.current); } set(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { error: err, loading: false })); }); onErrorPersist(err, args); }, [onErrorPersist]); // @ts-ignore var asyncInstanceRef = (0, react_1.useRef)(); if (!asyncInstanceRef.current) { asyncInstanceRef.current = new Async_1.default(asyncFnPersist, { cacheKey: cacheKey, cacheTime: cacheTime, persisted: persisted, formatResult: internalFormatRef.current, onSuccess: handleSuccess, onError: handleError, onFinally: onFinallyPersist, onBefore: handleBefore, debounceInterval: debounceInterval, throttleInterval: throttleInterval, pollingInterval: pollingInterval, pollingWhenHidden: pollingWhenHidden, refreshOnWindowFocus: refreshOnWindowFocus, focusTimespan: focusTimespan }); } (0, useUpdateEffect_1.default)(function () { asyncInstanceRef.current.updateOptions({ cacheKey: cacheKey, cacheTime: cacheTime, persisted: persisted, formatResult: internalFormatRef.current, onSuccess: handleSuccess, onError: handleError, onFinally: onFinallyPersist, onBefore: handleBefore, debounceInterval: debounceInterval, throttleInterval: throttleInterval, pollingInterval: pollingInterval, pollingWhenHidden: pollingWhenHidden, refreshOnWindowFocus: refreshOnWindowFocus, focusTimespan: focusTimespan }); }, [ onSuccessPersist, onErrorPersist, cacheKey, cacheTime, persisted, debounceInterval, throttleInterval, onFinallyPersist, onBeforePersist, pollingInterval, pollingWhenHidden, refreshOnWindowFocus, focusTimespan, handleSuccess, handleError, handleBefore ]); // 执行异步 var run = (0, react_1.useCallback)(function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return asyncInstanceRef.current.run.apply(asyncInstanceRef.current, args); }, []); // 使用上一次执行异步的参数,重新执行 var refresh = (0, react_1.useCallback)(function () { return asyncInstanceRef.current.refresh(); }, []); var cancel = (0, react_1.useCallback)(function () { asyncInstanceRef.current.cancel(); // 取消延迟loading if (loadingDelayTimerRef.current) { clearTimeout(loadingDelayTimerRef.current); } set(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { loading: false })); }); }, []); // 突变 var mutate = function (newData) { if (typeof newData === 'function') { // @ts-ignore set(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { data: newData(state.data) })); }); } else { set(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { data: newData })); }); } }; // autoRun=true 时,refreshDeps 变化,将重新执行 (0, useUpdateEffect_1.default)(function () { // 区分 React.StrictMode 下触发 if (autoRun && (0, ut2_1.isArray)(refreshDeps) && refreshDeps.length > 0) { refresh(); } }, [autoRun].concat(refreshDeps)); (0, react_1.useEffect)(function () { // 默认自动执行 if (autoRun) { // 支持默认参数 var fmtDefaultParams = (0, ut2_1.isArray)(defaultParams) ? defaultParams : (typeof defaultParams !== 'undefined' ? [defaultParams] : []); run.apply(void 0, fmtDefaultParams); } // 如果销毁过,可以重新恢复异步实例 asyncInstanceRef.current.resume(); return function () { cancel(); asyncInstanceRef.current.destroy(false); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return tslib_1.__assign(tslib_1.__assign({}, state), { run: run, cancel: cancel, mutate: mutate, refresh: refresh }); }; exports.default = useAsync;