Debouncing là kỹ thuật trì hoãn thực thi một hàm cho đến khi một khoảng thời gian yên tĩnh đã trôi qua kể từ lần gọi cuối cùng. Nó giảm thiểu các lần gọi hàm không cần thiết — đặc biệt hữu ích cho các sự kiện diễn ra liên tục như scroll, resize, input, hoặc gọi API tìm kiếm.
Vấn đề thực tế: Thanh tìm kiếm
Người dùng gõ "Tutorix study kit" (17 ký tự) → 17 lần gọi API. Nếu hàng triệu người cùng làm → quá tải server và làm chậm trình duyệt.
Giải pháp Debounce
Đặt thời gian chờ (ví dụ 300ms). Chỉ khi người dùng ngưng gõ quá 300ms thì mới gọi API. Trong khoảng đó, các lần gõ trước bị hủy.
Cơ chế
- Mỗi lần sự kiện xảy ra →
clearTimeouttimer cũ. - Tạo timer mới với
setTimeout. - Chỉ khi không có sự kiện mới trong khoảng delay → hàm thực thi.
Triển khai hàm debounce
function debounce(func, delay) {
let timerId;
return function(...args) {
const context = this;
clearTimeout(timerId);
timerId = setTimeout(() => func.apply(context, args), delay);
};
}
Ví dụ hoàn chỉnh: Xử lý click button
<button id="debounceBtn">Debounce Click</button>
<script>
const btn = document.getElementById('debounceBtn');
const debouncedAlert = debounce(function() {
alert('Chỉ thực thi 1 lần sau 2 giây yên tĩnh!');
}, 2000);
btn.addEventListener('click', debouncedAlert);
</script>
Kết quả: Click liên tục trong 2 giây → chỉ hiển thị 1 alert sau khi ngưng click 2 giây.
So sánh: Debounce vs Throttle
| Đặc điểm | Debounce | Throttle |
|---|---|---|
| Cơ chế | Chờ yên tĩnh mới chạy | Chạy theo khoảng thời gian cố định |
| Phù hợp | Tìm kiếm, auto-save, validate form | Scroll, resize, game loop |
| Số lần chạy | Tối đa 1 lần sau chuỗi sự kiện | Đều đặn theo interval |
Lưu ý
- Debounce không phù hợp cho các hành động cần phản hồi tức thì (ví dụ: click nút "Mua ngay").
- Có thể dùng
lodash.debouncehoặc_.debounce(Underscore/Lodash) cho production.