Event rate limiting prevents performance degradation in responsive interfaces. Two fundamental patterns govern high-frequency event handlign: debouncing consolidates multiple sequential calls into a single execution after a pause, while throttling enforces a maximum execution frequency regardless of trigger count.
Debounce Implementation
Deboucne delays function execution until a specified idle period elapses following the last invocation. This pattern suits input validation, search suggestions, and window resize completion detection.
export const createDebounce = (handler, idlePeriod) => {
let scheduledTask;
return function(...invocationArgs) {
clearTimeout(scheduledTask);
scheduledTask = setTimeout(() => {
handler.apply(this, invocationArgs);
}, idlePeriod);
};
};
Throttle Implementation
Throttle guarantees function execution at most once per designated timeframe, ideal for scroll listeners, mouse movement tracking, and drag operations.
export const createThrottle = (handler, minimumInterval) => {
let lastInvocation = 0;
return function(...invocationArgs) {
const currentTime = Date.now();
if (currentTime - lastInvocation >= minimumInterval) {
lastInvocation = currentTime;
handler.apply(this, invocationArgs);
}
};
};
Vue Integration Strategies
For global availability across components in Vue 2:
import Vue from 'vue';
import { createDebounce, createThrottle } from './utils';
Vue.prototype.$debounce = createDebounce;
Vue.prototype.$throttle = createThrottle;
For component-local usage with proper cleanup:
import { createDebounce } from '@/utils/timing';
export default {
data() {
return {
searchTerm: '',
debouncedQuery: null
};
},
created() {
this.debouncedQuery = createDebounce(this.fetchResults, 400);
},
beforeDestroy() {
this.debouncedQuery = null;
},
methods: {
fetchResults(query) {
// API implementation
},
handleInput(event) {
this.searchTerm = event.target.value;
this.debouncedQuery(this.searchTerm);
}
}
};
Scroll Monitoring Example
export default {
mounted() {
this.optimizedScroll = createThrottle(this.handleScroll, 150);
window.addEventListener('scroll', this.optimizedScroll);
},
beforeDestroy() {
window.removeEventListener('scroll', this.optimizedScroll);
},
methods: {
handleScroll() {
const position = window.scrollY;
// Position tracking logic
}
}
};
Critical Implementation Details
Timer references must be cleared when components destroy to prevent memory leaks and state updates on unmounted instances. When applying these utilities to template event listeners, bind the returned function rather than re-creating it on each render to maintain closure state.
For Vue 3 Composition API implementations, encapsulate these patterns within reusable composables:
import { onUnmounted } from 'vue';
export function useDebouncedCallback(callback, delay) {
let timeoutId;
const debouncedFn = (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => callback(...args), delay);
};
onUnmounted(() => clearTimeout(timeoutId));
return debouncedFn;
}