Khi Xây Dựng Ứng Dụng Web Hiện Đại, Hiệu Suất Là Quan Trọng
Khi xây dựng các ứng dụng web hiện đại, hiệu suất là một yếu tố không thể bỏ qua. Việc nhập liệu trong thanh tìm kiếm, thay đổi kích thước cửa sổ hay cuộn trang có thể kích hoạt hàng trăm sự kiện mỗi giây. Nếu mỗi sự kiện thực thi logic tốn kém (như gọi API), ứng dụng của bạn sẽ trở nên chậm chạp.
Đó là lý do tại sao Debouncing và Throttling là hai kỹ thuật quan trọng giúp kiểm soát tần suất thực thi sự kiện.
⏱ Debouncing
Debouncing đảm bảo rằng một hàm chỉ được thực thi sau một khoảng thời gian nhất định kể từ sự kiện cuối cùng.
👉 Trường hợp sử dụng: Nhập liệu tìm kiếm (API chỉ nên được kích hoạt sau khi người dùng dừng nhập liệu).
✅ Ví dụ React: Debounce với useEffect
javascript
import React, { useState, useEffect } from "react";
function SearchBox() {
const [query, setQuery] = useState("");
useEffect(() => {
const handler = setTimeout(() => {
if (query) {
console.log("Gọi API với:", query);
}
}, 500); // chờ 500ms sau khi nhập liệu cuối
return () => clearTimeout(handler);
}, [query]);
return <input onChange={(e) => setQuery(e.target.value)} />;
}
✅ Ví dụ Angular: Debounce với RxJS
javascript
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime } from 'rxjs/operators';
@Component({
selector: 'app-search',
template: `<input [formControl]="searchControl" />`
})
export class SearchComponent {
searchControl = new FormControl();
constructor() {
this.searchControl.valueChanges
.pipe(debounceTime(500)) // chờ 500ms
.subscribe(value => console.log("Gọi API với:", value));
}
}
⚡ Throttling
Throttling đảm bảo rằng một hàm chỉ được thực thi tối đa một lần trong một khoảng thời gian nhất định.
👉 Trường hợp sử dụng: Sự kiện thay đổi kích thước cửa sổ hoặc cuộn trang.
✅ Ví dụ React: Throttle Scroll
javascript
import React, { useEffect } from "react";
function ScrollTracker() {
useEffect(() => {
const handleScroll = () => {
console.log("Vị trí cuộn:", window.scrollY);
};
const throttled = throttle(handleScroll, 1000);
window.addEventListener("scroll", throttled);
return () => window.removeEventListener("scroll", throttled);
}, []);
const throttle = (fn, limit) => {
let inThrottle;
return function (...args) {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
};
return <h2>Cuộn trang nào!</h2>;
}
✅ Ví dụ Angular: Throttle với RxJS
javascript
import { Component, HostListener } from '@angular/core';
import { fromEvent } from 'rxjs';
import { throttleTime } from 'rxjs/operators';
@Component({
selector: 'app-scroll-tracker',
template: `<h2>Cuộn trang nào!</h2>`
})
export class ScrollTrackerComponent {
ngOnInit() {
fromEvent(window, 'scroll')
.pipe(throttleTime(1000)) // thực thi mỗi 1 giây
.subscribe(() => {
console.log("Vị trí cuộn:", window.scrollY);
});
}
}
📊 So Sánh Debounce và Throttle
Tính năng | Debounce | Throttle |
---|---|---|
Thực thi | Sau khi không hoạt động | Theo khoảng thời gian đều đặn |
Trường hợp sử dụng | Tìm kiếm, tự động hoàn thành, kết thúc thay đổi kích thước | Cuộn, thay đổi kích thước, di chuyển chuột |
✅ Kết Luận
- Sử dụng Debouncing khi bạn muốn chờ cho đến khi người dùng dừng thực hiện một hành động.
- Sử dụng Throttling khi bạn muốn giới hạn tần suất thực thi của một hành động trong thời gian liên tục.
Cả hai kỹ thuật này đều rất cần thiết cho các ứng dụng mượt mà và hiệu suất cao trong React và Angular.
Các Thực Hành Tốt Nhất
- Sử dụng thư viện bên ngoài: Có nhiều thư viện như Lodash cung cấp các hàm debounce và throttle sẵn có, giúp bạn tiết kiệm thời gian.
- Kiểm tra hiệu suất: Luôn theo dõi hiệu suất của ứng dụng sau khi áp dụng các kỹ thuật này.
Những Cạm Bẫy Thường Gặp
- Không sử dụng đúng bối cảnh: Đảm bảo rằng bạn chọn Debounce cho các hành động dựa trên sự nhập liệu và Throttle cho các hành động liên tục như cuộn.
- Chọn khoảng thời gian không hợp lý: Thời gian chờ quá ngắn có thể không mang lại hiệu quả như mong đợi.
Mẹo Tăng Cường Hiệu Suất
- Tối ưu hóa mã: Đảm bảo rằng các hàm bạn đang sử dụng trong debounce hoặc throttle không có logic tốn kém.
- Kiểm tra trên nhiều thiết bị: Hiệu suất có thể khác nhau trên các loại thiết bị khác nhau.
Câu Hỏi Thường Gặp (FAQ)
- Debounce và Throttle có thể sử dụng cùng nhau không?
Có, bạn có thể sử dụng cả hai kỹ thuật trong cùng một ứng dụng, tùy thuộc vào từng trường hợp sử dụng. - Khi nào nên chọn Debounce thay vì Throttle?
Khi bạn muốn chỉ thực thi sau khi người dùng ngừng hành động trong một khoảng thời gian nhất định.
Kết Luận
Việc áp dụng Debounce và Throttle một cách đúng đắn sẽ giúp cải thiện đáng kể hiệu suất ứng dụng của bạn, mang lại trải nghiệm người dùng tốt hơn và giảm tải cho server. Hãy thử nghiệm và tìm hiểu cách chúng có thể giúp bạn trong các dự án sắp tới!