1. Vấn Đề Tắc Nghẽn Khi Xử Lý Sự Kiện Tần Suất Cao
Trong quá trình phát triển ứng dụng web, các sự kiện từ phía người dùng như gõ phím (input/keyup), cuộn chuột (scroll), thay đổi kích thước cửa sổ (resize) hoặc di chuột (mousemove) có thể kích hoạt từ 50 đến 100 lần mỗi giây.
Nếu mỗi lần sự kiện diễn ra bạn đều gửi một API request về máy chủ hoặc thực hiện tính toán DOM phức tạp:
- Trình duyệt của người dùng bị giật lag (Drop FPS) do luồng chính (Main Thread) bị nghẽn.
- Máy chủ Backend bị quá tải CPU và cơ sở dữ liệu bị tê liệt bởi hàng nghìn request vô nghĩa.
Hai kỹ thuật kinh điển để giải quyết bài toán này là Debouncing và Throttling.
2. Phân Biệt Chi Tiết: Debounce vs Throttle
Sự kiện liên tục: |||||||||||||||||||||||||||||||||||||||||||||
─────────────────────────────────────────────
Debounce (300ms): | (Chỉ thực thi khi người dùng dừng hẳn)
Throttle (300ms): | | | | | (Thực thi định kỳ mỗi 300ms một lần)
2.1. Debouncing (Trì Hoãn Đến Khi Dừng Lại)
- Cơ chế: Hoãn thực thi hàm cho đến khi không còn sự kiện nào phát sinh trong một khoảng thời gian chờ nhất định (
delay). Nếu có sự kiện mới xuất hiện trước khi hết thời gian chờ, bộ đếm thời gian sẽ được đặt lại từ đầu. - Ứng dụng điển hình: Ô tìm kiếm gợi ý tự động (Auto-complete Search), kiểm tra tính hợp lệ của username/email khi nhập form.
2.2. Throttling (Giới Hạn Tần Suất Định Kỳ)
- Cơ chế: Đảm bảo hàm chỉ được thực thi tối đa một lần trong mỗi khoảng thời gian cố định, bất kể sự kiện có được kích hoạt bao nhiêu lần đi nữa.
- Ứng dụng điển hình: Sự kiện cuộn trang vô tận (Infinite Scroll), theo dõi vị trí cuộn trang để cập nhật thanh tiến trình (Reading Progress Bar), di chuyển camera trong WebGL/Canvas.
3. Code Mẫu Triển Khai Chuẩn TypeScript
3.1. Implementation Của Hàm Debounce
export function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number = 300
): (...args: Parameters<T>) => void {
let timerId: NodeJS.Timeout | null = null;
return function (...args: Parameters<T>) {
if (timerId) {
clearTimeout(timerId);
}
timerId = setTimeout(() => {
fn(...args);
timerId = null;
}, delay);
};
}
3.2. Custom Hook useDebounce Trong React / Next.js
import { useState, useEffect } from 'react';
export function useDebounce<T>(value: T, delay: number = 300): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(timer);
};
}, [value, delay]);
return debouncedValue;
}
4. Bảo Vệ Máy Chủ Ở Tầng Hạ Tầng (Rate Limiting)
Bên cạnh việc tối ưu ở Client-side, máy chủ Cloud VPS cần phải thiết lập lớp phòng thủ Rate Limiting ở tầng Nginx để ngăn chặn tin tặc cố tình gửi request spam bỏ qua mã JavaScript client.
# Giới hạn API search tối đa 5 requests/giây cho mỗi IP
limit_req_zone $binary_remote_addr zone=search_limit:10m rate=5r/s;
location /api/v1/search {
limit_req zone=search_limit burst=10 nodelay;
proxy_pass http://127.0.0.1:3000;
}
🛡️ Hạ tầng bền bỉ: Vận hành ứng dụng trên Cloud VPS KVM NVMe tại ThueCloud để hệ thống luôn ổn định trước mọi đợt traffic đột biến!


