EN/CH Mode
BRUCE_FE JS Interview Notes - User Interaction Optimization - Throttle and Debounce
In-depth understanding of Throttle and Debounce techniques in JavaScript, including their differences, implementation principles, applicable scenarios, and practical examples to master frontend performance optimization and common interview questions.
EN/CH Mode

Lazy to read articles? Then watch videos!
What are Throttle and Debounce? Why do we need them?
Throttle and Debounce are two common frontend performance optimization techniques used to control the execution frequency of high-frequency events (such as scrolling, searching, and window resizing).
- •Throttle: Limits a function to execute only once within a time period, regardless of how many times it's triggered. Like "execute at most once every N milliseconds".
- •Debounce: Merges multiple consecutive triggers into one, executing only after waiting a period of time after the last trigger. Like "wait N milliseconds without new triggers before executing".
These two techniques are very important for optimizing frontend performance and enhancing user experience:
- •Reduce unnecessary function calls
- •Decrease API request frequency
- •Optimize resource-intensive calculations
- •Reduce DOM operation frequency
Throttle Implementation and Principles
The core concept of throttling is 'ensuring that a function executes at most once within a specified time period':
function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
func.apply(this, args);
lastCall = now;
}
};
}
// Usage example
const throttledScroll = throttle(() => {
console.log('Scroll position:', window.scrollY);
}, 300);
window.addEventListener('scroll', throttledScroll);Diagram of Throttle execution principle:
Event triggers: ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
Function executes: ↓ ↓ ↓
Timeline: |--------|--------|------->
300ms 300ms 300msDebounce Implementation and Principles
The core concept of debouncing is 'waiting until there are no new calls within a specified time period before executing a function':
function debounce(func, delay) {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
// Usage example
const searchInput = document.getElementById('search');
const debouncedSearch = debounce((e) => {
console.log('Search keyword:', e.target.value);
// fetchResults(e.target.value);
}, 500);
searchInput.addEventListener('input', debouncedSearch);Diagram of Debounce execution principle:
Event triggers: ↓ ↓ ↓ ↓ ↓ ↓
Reset timer: ⟳ ⟳ ⟳ ⟳ ⟳ ⟳
Function executes: ✓ ✓
Timeline: |-----|-----|-----|-----|---->
Waiting Waiting Execute Waiting ExecuteUse Case Comparison
Comparing Suitable Scenarios for Throttle and Debounce:
| Technique | Suitable Scenarios | Practical Applications |
|---|---|---|
| Throttle | Scroll Event Handling | Infinite scroll loading in social media, checking scroll position every 300ms |
| Game Button Controls | Limiting players to shooting at most 5 bullets per second in a shooting game | |
| Map Dragging/Zooming | When dragging Google Maps, requesting map data only every 100ms | |
| Canvas Drawing | In drawing applications, brush follows mouse to draw points at fixed intervals | |
| Debounce | Search Box Input | Google search box sends search request only 500ms after stopping typing |
| Form Validation | In registration forms, checking if email is already in use only after the user finishes typing | |
| Auto-Save | Google Docs auto-saves content 2 seconds after the user stops typing | |
| Window Resizing | Responsive websites reformat only after the user finishes resizing the window |
Practical Applications and Performance Differences
Case 1: Scroll Event Optimization (Using Throttle)
Before optimization, scrolling might trigger hundreds of function calls:
// Unoptimized - Executes on every scroll
window.addEventListener('scroll', () => {
loadMoreContent();
});
// Optimized - Executes at most once every 200ms
window.addEventListener('scroll', throttle(() => {
loadMoreContent();
}, 200));Case 2: Auto-saving Forms (Using Debounce)
Before optimization, typing each character would trigger a save:
// Unoptimized - Saves on every input
editor.addEventListener('input', saveContent);
// Optimized - Saves only 500ms after stopping input
editor.addEventListener('input', debounce(saveContent, 500));🔥 Common Interview Questions
(1) What is the main difference between Throttle and Debounce?
Answer:Throttle controls a function to execute at most once within a time period, regardless of how many times it's triggered, suitable for continuous events like scrolling. For example: on an e-commerce website, when users scroll the page, using Throttle to check every 200ms whether more products need to be loaded, instead of triggering on every scroll.Debounce merges multiple consecutive triggers into one, executing only after waiting a period of time after the last trigger, suitable for scenarios that require only the final result of consecutive triggers, like searching. For example: in a search box, when a user quickly types "React tutorial", using Debounce to wait 500ms after the user stops typing before sending an API request, rather than sending a request for each keystroke.
(2) What is the execution result of the following code?
let count = 0;
const btn = document.getElementById('btn');
const throttledClick = throttle(() => {
console.log(`點擊次數: ${++count}`);
}, 1000);
// 假設使用者在 2 秒內快速點擊 5 次
btn.addEventListener('click', throttledClick);- At 0 seconds: "Click count: 1" (executes immediately on first click)
- At 1 second: "Click count: 2" (executes after the 1-second interval)
- At 2 seconds: "Click count: 3" (executes after the 1-second interval)
(3) What is the execution result of the following debounce code?
let count = 0;
const searchInput = document.getElementById('search');
const debouncedSearch = debounce(() => {
console.log(`搜尋次數: ${++count}`);
}, 500);
// 假設使用者在 1 秒內快速輸入 5 個字元
searchInput.addEventListener('input', debouncedSearch);- At 1.5 seconds: "Search count: 1" (executes 500ms after the last input)
(4) Implement a simple search box Debounce
Answer:Here is a simple implementation of a search box with Debounce:
// HTML: <input id="search" type="text" placeholder="Search...">
// HTML: <div id="results"></div>
function debounce(func, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => func(...args), delay);
};
}
const searchInput = document.getElementById('search');
const resultsDiv = document.getElementById('results');
const handleSearch = debounce((event) => {
const query = event.target.value;
resultsDiv.textContent = `Searching: ${query}`;
// In a real application, an API request would be sent here
}, 300);
searchInput.addEventListener('input', handleSearch);