import type { DebouncedFunc, DebounceSettings } from 'lodash-es'; import { debounce } from 'lodash-es'; import { computed, ref, watchEffect } from 'vue'; import type { UseRequestPlugin } from '../types'; const useDebouncePlugin: UseRequestPlugin = ( fetchInstance, { debounceWait, debounceLeading, debounceTrailing, debounceMaxWait }, ) => { const debouncedRef = ref>(); const options = computed(() => { const ret: DebounceSettings = {}; if (debounceLeading !== undefined) { ret.leading = debounceLeading; } if (debounceTrailing !== undefined) { ret.trailing = debounceTrailing; } if (debounceMaxWait !== undefined) { ret.maxWait = debounceMaxWait; } return ret; }); watchEffect(() => { if (debounceWait) { const _originRunAsync = fetchInstance.runAsync.bind(fetchInstance); debouncedRef.value = debounce( (callback) => { callback(); }, debounceWait, options.value, ); // debounce runAsync should be promise // https://github.com/lodash/lodash/issues/4400#issuecomment-834800398 fetchInstance.runAsync = (...args) => { return new Promise((resolve, reject) => { debouncedRef.value?.(() => { _originRunAsync(...args) .then(resolve) .catch(reject); }); }); }; return () => { debouncedRef.value?.cancel(); fetchInstance.runAsync = _originRunAsync; }; } }); if (!debounceWait) { return {}; } return { onCancel: () => { debouncedRef.value?.cancel(); }, }; }; export default useDebouncePlugin;