Skip to content

Instantly share code, notes, and snippets.

@NoTimeForHero
Created April 29, 2026 21:01
Show Gist options
  • Select an option

  • Save NoTimeForHero/6e09d2d9689949b407eced05effe82da to your computer and use it in GitHub Desktop.

Select an option

Save NoTimeForHero/6e09d2d9689949b407eced05effe82da to your computer and use it in GitHub Desktop.
import { getCurrentScope, onScopeDispose } from 'vue';
type AnyFn = (...args: any[]) => any;
interface UseDebounceFnReturn<T extends AnyFn> {
(...args: Parameters<T>): void;
cancel: () => void;
flush: () => void;
}
/**
* Оборачивает функцию в debounce-логику.
* В отличии от версии из пакета VueUse поддерживает flush и cancel методы.
*
* @param fn — исходная функция
* @param ms — задержка в миллисекундах (по умолчанию 200)
* @returns — debounced-обёртка с методами `cancel` и `flush`
*/
export function useFastDebounceFn<T extends AnyFn>(
fn: T,
ms: number = 200,
): UseDebounceFnReturn<T> {
let timeoutId: ReturnType<typeof setTimeout> | null = null;
let lastArgs: Parameters<T> | null = null;
const cancel = (): void => {
lastArgs = null;
if (!timeoutId) return;
clearTimeout(timeoutId);
timeoutId = null;
};
const flush = (): void => {
if (timeoutId == null) return;
if (lastArgs == null) return;
fn(...lastArgs);
cancel();
};
const debounced = ((...args: Parameters<T>): void => {
lastArgs = args;
if (timeoutId !== null) clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
timeoutId = null;
const currArgs = lastArgs;
lastArgs = null;
if (currArgs == null) return;
fn(...currArgs);
}, ms);
}) as UseDebounceFnReturn<T>;
debounced.cancel = cancel;
debounced.flush = flush;
// Автоматическая очистка при уничтожении scope (компонента / effectScope)
if (getCurrentScope()) onScopeDispose(cancel);
return debounced;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment