Trong các ứng dụng web hiện nay, JavaScript thường đảm nhận cả hai vai trò: điều khiển logic và xử lý giao diện người dùng (UI). Tuy nhiên, vì JavaScript là ngôn ngữ chạy trên single-thread, mọi tác vụ – từ render giao diện đến xử lý tính toán – đều chia sẻ chung một luồng chính.
Điều này dẫn đến tình trạng quen thuộc: UI bị đơ hoặc giật lag khi bạn chạy một đoạn code tính toán nặng.
Vậy có cách nào để JavaScript vừa xử lý được tác vụ phức tạp, vừa giữ được trải nghiệm mượt mà cho người dùng?
Câu trả lời là: Web Worker.

1. Web Worker là gì?
Web Worker là cơ chế cho phép JavaScript chạy trên một luồng riêng biệt (background thread) tách khỏi luồng chính (main thread).
Nhờ đó, bạn có thể thực hiện các tác vụ nặng như xử lý dữ liệu, tính toán, mã hóa, mà không làm ảnh hưởng đến UI.
Nói cách khác:
Main thread tiếp tục cập nhật giao diện, trong khi Worker thread âm thầm xử lý phần logic phía sau.
2. Cách hoạt động của Web Worker
Khi bạn tạo một Web Worker, trình duyệt sẽ mở ra một “thread con” độc lập. Hai luồng này không chia sẻ chung bộ nhớ, mà chỉ giao tiếp qua message (thông điệp).
Luồng chính gửi dữ liệu bằng postMessage(), Worker nhận qua onmessage, xử lý, rồi gửi ngược lại kết quả.
Cấu trúc đơn giản
worker.js
self.onmessage = function (e) {
const result = e.data.num * 2;
self.postMessage(result);
};
main.js
const worker = new Worker('worker.js');
worker.postMessage({ num: 5 });
worker.onmessage = function (e) {
console.log('Kết quả:', e.data); // 10
};
Lưu ý:
Web Worker không truy cập được window, document, hay DOM API.
Nó hoạt động hoàn toàn độc lập, chỉ làm việc với dữ liệu và logic.
3. Khi nào nên dùng Web Worker?
Không phải tác vụ nào cũng cần Worker. Dưới đây là một số tình huống phổ biến:
- Xử lý ảnh, video, hoặc dữ liệu lớn: Tránh chặn giao diện
- Tính toán phức tạp (AI, thuật toán, mã hóa): Tác vụ tốn CPU
4. Ví dụ: Tính Fibonacci bằng Web Worker
Nếu bạn từng viết hàm Fibonacci theo kiểu đệ quy, bạn sẽ biết nó rất tốn CPU.
Chạy trên main thread, giao diện có thể bị “đơ cứng” trong vài giây.
Không dùng Web Worker:
function fibonacci(n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(45)); // UI bị đơ
Dùng Web Worker:
fib-worker.js
self.onmessage = function (e) {
const fib = n => (n < 2 ? n : fib(n - 1) + fib(n - 2));
const result = fib(e.data);
self.postMessage(result);
};
main.js
const worker = new Worker('fib-worker.js');
worker.postMessage(45);
worker.onmessage = e => console.log('Kết quả:', e.data);
Khi chạy ví dụ này, bạn sẽ thấy UI vẫn phản hồi bình thường trong khi Worker xử lý ở background.
5. SharedWorker, ServiceWorker và Worker Pool
SharedWorker
Cho phép nhiều tab hoặc iframe dùng chung một worker, giúp tiết kiệm tài nguyên khi có nhiều client truy cập cùng nguồn dữ liệu.
ServiceWorker
Không giống Web Worker. Đây là loại worker chuyên dụng cho caching, offline, và push notification trong PWA.
Worker Pool
Khi bạn có nhiều tác vụ nhỏ, thay vì tạo hàng loạt worker mới, hãy tái sử dụng qua pool để giảm chi phí khởi tạo thread.
6. Lưu ý khi dùng Web Worker
-
Worker không thể thao tác DOM. Nếu cần cập nhật UI, hãy gửi dữ liệu kết quả về main thread.
-
Việc tạo quá nhiều worker cùng lúc có thể khiến CPU quá tải.
-
Dữ liệu truyền giữa main và worker được copy, không phải shared memory (trừ khi dùng SharedArrayBuffer).
7. Kết luận
Web Worker là một trong những công cụ mạnh mẽ nhưng ít được khai thác đúng mức trong JavaScript.
Khi ứng dụng cần xử lý dữ liệu lớn hoặc thực hiện tác vụ tốn CPU, hãy để Web Worker gánh phần nặng nề đó — còn main thread tập trung giữ trải nghiệm mượt mà cho người dùng.
Một khi bạn hiểu và áp dụng đúng Web Worker, bạn sẽ thấy web app của mình “nhẹ nhàng như gió”.







