Cả hai đều giới hạn tần suất một hàm chạy để phản ứng với các sự kiện nhanh, lặp lại — nhưng với các chiến lược thời gian khác nhau.
- Debounce: chỉ chạy hàm sau khi hoạt động dừng lại trong N ms. Reset bộ đếm thời gian ở mỗi lần gọi. → "chờ cho đến khi họ xong."
- Throttle: chạy hàm tối đa một lần mỗi N ms trong suốt hoạt động liên tục. → "chạy ở một tốc độ đều đặn."
text
events: x x x x x x x ........ x x x
debounce: ↑ (kích hoạt một lần, sau khi tạm dừng)
throttle: ↑ ↑ ↑ ↑ (kích hoạt định kỳ)
Cài đặt debounce
js
function debounce(fn, ms) {
let timer;
return (...args) => {
clearTimeout(timer); // hủy lần gọi đã lên lịch trước đó
timer = setTimeout(() => fn(...args), ms); // lên lịch một lần mới
};
}
const search = debounce(q => api.search(q), 300); // chỉ tìm kiếm sau khi gõ tạm dừng
Cài đặt throttle
js
function throttle(fn, ms) {
let last = 0;
return (...args) => {
const now = Date.now();
if (now - last >= ms) { last = now; fn(...args); } // chạy tối đa mỗi ms
};
}
Khi nào dùng cái nào
- Debounce: tìm-kiếm-khi-gõ, tự động lưu, kết thúc resize, validate sau khi người dùng ngừng gõ — bạn muốn giá trị cuối cùng.
- Throttle: scroll handler, mousemove, kéo (drag), giới hạn tốc độ — bạn muốn cập nhật định kỳ trong khi hành động đang diễn ra.
Tại sao điều này quan trọng
Cả hai ngăn việc kích hoạt công việc tốn kém (gọi API, tính lại layout) hàng trăm lần mỗi giây, đây là một kỹ thuật hiệu năng front-end then chốt.
Các thư viện như lodash cung cấp các phiên bản mạnh mẽ với tùy chọn leading/trailing.
