Cơn ác mộng mang tên "Sự kiện quá tải"
Bạn đã bao giờ code một ô tìm kiếm mà cứ mỗi lần người dùng gõ một phím, hệ thống lại hì hục gọi API một lần chưa? Hay tệ hơn, một hiệu ứng cuộn trang (scroll) khiến quạt tản nhiệt của laptop kêu to như tiếng động cơ phản lực? Đó chính là lúc website của bạn đang bị "ngộp" bởi hàng tá sự kiện (events) xảy ra liên tục trong tích tắc.

Nếu không xử lý khéo, trình duyệt sẽ phải gồng mình tính toán lại giao diện (re-flow) hoặc gọi mạng vô tội vạ, dẫn đến tình trạng giật lag cực kỳ khó chịu. Để giải quyết vấn đề này, chúng ta có hai "vị cứu tinh" kinh điển trong JavaScript: Debounce và Throttle. Dù nghe có vẻ cao siêu, nhưng chúng thực chất chỉ là cách chúng ta dạy trình duyệt cách... làm việc có kế hoạch hơn.
Việc tối ưu hóa sự kiện không chỉ giúp giao diện mượt mà hơn mà còn tiết kiệm tài nguyên server đáng kể, tương tự như cách Next.js 15 và Turbopack giúp tăng tốc độ build dự án vậy.
Debounce: Chờ đợi là hạnh phúc
Hãy tưởng tượng bạn đang đứng trước cửa thang máy. Mỗi khi có một người bước vào, thang máy sẽ chờ thêm 5 giây nữa xem còn ai không rồi mới đóng cửa. Nếu trong 5 giây đó lại có người nữa bước vào, đồng hồ đếm ngược sẽ quay lại từ đầu. Thang máy chỉ thực sự chạy khi không còn ai vào thêm nữa trong suốt 5 giây đó. Đó chính là Debounce.
Kỹ thuật này cực kỳ hữu ích cho các ô tìm kiếm (Search Input). Thay vì gọi API ngay lập tức khi người dùng vừa gõ chữ "A", chúng ta sẽ đợi họ gõ xong cả từ "Apple" rồi mới bắt đầu hành động. Điều này giúp tránh việc gửi hàng chục yêu cầu mạng dư thừa lên server.
function debounce(func, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), delay);
};
}Bằng cách này, hàm func sẽ chỉ được thực thi một lần duy nhất sau khi người dùng ngừng thao tác trong khoảng thời gian delay. Đây là cách cực hay để giữ cho ứng dụng của bạn không bị "bay màu" vì quá tải request.
Throttle: Tiết kiệm sức lao động
Ngược lại với Debounce, Throttle giống như việc tưới cây bằng hệ thống phun nước tự động. Dù bạn có bấm nút liên tục bao nhiêu lần đi chăng nữa, hệ thống cũng chỉ phun nước đúng 1 lần mỗi phút. Nó đảm bảo rằng một hành động chỉ được thực hiện tối đa một lần trong một khoảng thời gian nhất định.
Kỹ thuật này là "chân á" cho các sự kiện xảy ra với tần suất dày đặc như scroll (cuộn chuột) hoặc resize (thay đổi kích thước màn hình). Thay vì tính toán lại vị trí các phần tử 100 lần mỗi giây, bạn chỉ cho phép nó chạy 10 lần mỗi giây (mỗi 100ms một lần). Hiệu quả mang lại là website vẫn phản hồi mượt mà mà CPU lại được "thở" phào nhẹ nhõm.
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}Việc làm chủ các kỹ thuật này cũng quan trọng như việc hiểu rõ các JavaScript Array Methods mới để xử lý dữ liệu một cách chuyên nghiệp và gọn gàng hơn.
Khi nào dùng cái nào?
Quy tắc ngón tay cái rất đơn giản: Nếu bạn muốn đợi đến khi người dùng ngừng hẳn hành động thì dùng Debounce (như gõ phím, lưu bản nháp tự động). Còn nếu bạn muốn hành động được thực hiện đều đặn trong khi hành động vẫn đang diễn ra thì chọn Throttle (như kiểm tra vị trí scroll để hiện nút Back to Top).
Đừng cố tự viết lại các hàm này trong dự án thực tế nếu bạn không quá rành. Hãy sử dụng các thư viện như Lodash hoặc các Hook có sẵn trong React để đảm bảo code chạy ổn định nhất có thể.
Tối ưu hiệu năng là một hành trình dài, nhưng chỉ cần bắt đầu từ những chi tiết nhỏ như việc kiểm soát sự kiện, bạn đã giúp người dùng có trải nghiệm tốt hơn rất nhiều. Vậy sau khi đã làm website mượt như lụa, liệu bạn có tò mò về cách chúng ta bảo mật những luồng dữ liệu đó không? Tìm hiểu thêm tại DIA DEMY nhé!




Vui lòng đăng nhập để bình luận.