UNPKG

@kcuf-hook/use-debounced

Version:
84 lines (82 loc) 3.05 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = useDebouncedCallback; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _react = require("react"); var _useIsUnmounted = _interopRequireDefault(require("@kcuf-hook/use-is-unmounted")); var _util = require("../util"); function useDebouncedCallback(fn, options) { var refFn = (0, _react.useRef)(fn); var refArgs = (0, _react.useRef)(null); // 上次调用 `fn` 的参数列表,执行后会被清空 var refTimeCalled = (0, _react.useRef)(0); // 上次调用 `fn` 的时间(但不一定执行) var refTimeInvoked = (0, _react.useRef)(0); // 上次真正执行 `fn` 的时间 var refTimerId = (0, _react.useRef)(null); var isUnmounted = (0, _useIsUnmounted.default)(); var _resolveOptions = (0, _util.resolveOptions)(options), delay = _resolveOptions.delay, delayMax = _resolveOptions.delayMax, immediate = _resolveOptions.immediate; refFn.current = fn; // always fresh (0, _react.useEffect)(function () { return function () { if (refTimerId.current) { clearTimeout(refTimerId.current); } refTimerId.current = null; }; }, []); return (0, _react.useMemo)(function () { function invokeFn() { var args = refArgs.current; if (args) { refArgs.current = null; refTimeInvoked.current = Date.now(); refFn.current.apply(refFn, (0, _toConsumableArray2.default)(args)); } } function startTimer(pendingFunc, wait) { if (refTimerId.current) { clearTimeout(refTimerId.current); } refTimerId.current = setTimeout(pendingFunc, wait); } function timerExpired() { if (isUnmounted()) { return; } if (Date.now() - refTimeCalled.current >= delay) { refTimerId.current = null; invokeFn(); return; } var time = Date.now(); var timeSinceLastCall = time - refTimeCalled.current; var timeSinceLastInvoke = time - refTimeInvoked.current; var timeWaiting = delay - timeSinceLastCall; var remainingWait = delayMax >= delay ? Math.min(timeWaiting, delayMax - timeSinceLastInvoke) : timeWaiting; startTimer(timerExpired, remainingWait); } function callFn() { var time = Date.now(); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } refArgs.current = args; refTimeCalled.current = time; if (immediate && !refTimerId.current) { invokeFn(); } if (delayMax >= delay && time - refTimeInvoked.current >= delayMax) { invokeFn(); startTimer(timerExpired, delay); } if (!refTimerId.current) { startTimer(timerExpired, delay); } } return callFn; }, [delay, delayMax, immediate, isUnmounted]); }