- vừa được xem lúc

Sử dụng Web Workers để xử lý tác vụ nặng trong trình duyệt

0 0 1

Người đăng: Vũ Nguyễn

Theo Viblo Asia

Giới thiệu

Trong các ứng dụng web hiện đại, hiệu suất là một yếu tố quan trọng ảnh hưởng trực tiếp đến trải nghiệm người dùng. Một trong những nguyên nhân chính gây ra tình trạng giật lag, hoặc block UI là do các tác vụ tính toán nặng (heavy tasks) được thực thi trực tiếp ngay trên (main thread).

Để giải quyết vấn đề này, JavaScript cung cấp giải pháp Web Workers, cho phép chạy các đoạn mã song song trong một luồng riêng biệt, giúp tránh xử lí trên main threadtăng hiệu suất ứng dụng.

1. Web Workers là gì?

Web Workers là một API của trình duyệt cho phép bạn thực thi JavaScript trong một luồng riêng biệt với luồng chính của ứng dụng.

  • Web Workers có thể giao tiếp với main thread thông qua postMessage.
  • Phù hợp để xử lý: tính toán nặng, phân tích dữ liệu, xử lý ảnh, nén file,...

2. Tại sao nên sử dụng Web Workers?

Lợi ích:

  • Không làm block UI: vì tác vụ không chạy trên main thread.
  • Cải thiện UX: giao diện vẫn phản hồi trong khi xử lý tác vụ.
  • Tăng hiệu suất khi xử lí các tác vụ tính toán phức tạp.

Khi không sử dụng Web Workers:

  • UI dễ bị đơ khi xử lý JSON lớn, vòng lặp nhiều, hoặc xử lí thuật toán nặng hoặc xử lí loop đệ quy nhiều vòng.
  • User có thể nhầm tưởng ứng dụng bị crash nếu không phản hồi.

3. Ví dụ về cách sử dụng Web Workers cho bài toán tính giai thừa

Giả sử bạn cần thực hiện phép tính giai thừa (n!) với BigInt – đây là một tác vụ có thể gây chậm hoặc "đơ" giao diện nếu xử lý trực tiếp trong main thread. Ở ví dụ này ta sử dụng Web Worker để tách hàm xử lí factorial ra luồng một luồng riêng không liên quan đến main thread

Ví dụ đơn giản gồm:

  • Một file Web Worker để tính giai thừa.
  • Một component React (TSX) gồm ô input, button nhấn để gửi dữ liệu vào worker file, và các thẻ p để hiển thị kết quả.

🧮 factorialWorker.ts – File worker

self.onmessage = function (e) { const number = e.data; const result = factorial(number); self.postMessage(result);
}; function factorial(n: number): BigInt { let result = BigInt(1); for (let i = 2; i <= n; i++) { result *= BigInt(i); } return result;
} export {};

🧑‍💻 FactorialCalculator.tsx – React component

import React, { useState, useRef } from "react"; const FactorialCalculator: React.FC = () => { const [input, setInput] = useState<number>(100000); const [result, setResult] = useState<number | null>(null); const [loading, setLoading] = useState(false); const [totalTime, setTotalTime] = useState(0); const workerRef = useRef<Worker | null>(null); const handleCalculate = () => { setResult(null); setTotalTime(0); setLoading(true); const startTime = performance.now(); // Start timing const worker = new Worker(new URL("@src/worker/factorialWorker", import.meta.url)); workerRef.current = worker; worker.postMessage(input); worker.onmessage = (e: MessageEvent<number>) => { const endTime = performance.now(); // End timing setTotalTime(endTime - startTime); // Calculate total time in milliseconds setResult(e.data); setLoading(false); worker.terminate(); }; }; return ( <div> <input type="number" value={input} onChange={(e) => setInput(Number(e.target.value))} placeholder="Nhập số nguyên dương" /> <button onClick={handleCalculate} disabled={loading}> {loading ? "Đang tính..." : "Tính giai thừa"} </button> {result !== null && <p>Kết quả: {result}</p>} {totalTime > 0 && <p>Thời gian tính toán: {totalTime.toFixed(3)} ms</p>} </div> );
}; export default FactorialCalculator;

Kết quả:

Khi không sử dụng Web Worker Khi sử dụng Web Worker

Ta có thể thấy khi sử dụng web-worker, UI không những không bị block mà còn mượt mà hơn rất nhiều so với khi không sử dụng. Đơn giản hơn thì ta có thể sử dụng Thư viện https://useworker.js.org/ để code nhanh hơn mà không cần tách hàm như trên 😄

4. Lưu ý khi sử dụng web worker

  • Không thể truy cập đến DOM từ trong worker file.
  • Đảm bảo luồng giao tiếp postMessage rõ ràng và không gây race condition.
  • Có thể dùng Comlink để đơn giản hóa giao tiếp.

5. Khi nào nên dùng Web Workers?

Tình huống Có nên dùng Worker?
Tính toán nặng như mã hóa, nén file ✅ Cần
Xử lý file JSON lớn (>1MB) ✅ Cần
Cập nhật UI đơn giản ❌ Không cần
Fetch API, gọi server ❌ Không cần (dùng async/await cho lẹ 😄)

6. Các option nâng cao khác

  • SharedWorker: chia sẻ worker giữa nhiều tab.
  • Service Worker: xử lý request, cache – khác với Web Worker.
  • OffscreenCanvas: render canvas trong worker (đặc biệt hữu ích với đồ họa).

Kết luận

Web Workers là công cụ mạnh mẽ giúp cải thiện hiệu suất của các ứng dụng web hiện đại. Việc tách biệt các tác vụ nặng ra khỏi luồng chính sẽ giúp UI luôn mượt mà, thân thiện với người dùng. Hãy cân nhắc sử dụng Web Workers khi bắt đầu thấy trình duyệt bị "đơ", "lag" khi chạy những tác vụ phức tạp.

Xem thêm các bài viết tại: vunguyenit.site

Bình luận

Bài viết tương tự

- vừa được xem lúc

Blog#173: Introduction to Advanced JavaScript Concepts - Advanced JavaScript Part 1

Hi, I'm Tuan, a Full-stack Web Developer from Tokyo . JavaScript is an essential language for web development, and learning advanced concepts can significantly improve your programming skills.

0 0 24

- vừa được xem lúc

Blog#174: 🤔Understanding Asynchronous JavaScript: 🔄Callbacks, 🤞Promises, and 🤝Async/Await

Hi, I'm Tuan, a Full-stack Web Developer from Tokyo . 1. Introduction to Asynchronous JavaScript. What is Asynchronous JavaScript.

0 0 30

- vừa được xem lúc

Blog#175: 🧐Mastering JavaScript's Execution Context and Closures🚀

Hi, I'm Tuan, a Full-stack Web Developer from Tokyo . 1. Understanding Execution Context. A Quick Overview.

0 0 30

- vừa được xem lúc

Blog#177: 🤔MAYBE YOU DON'T KNOW - 👌Using Node-Postgres in Node.js Express✨

Hi, I'm Tuan, a Full-stack Web Developer from Tokyo . In this article, we'll walk you through a step-by-step guide on using node-postgres with Node.

0 0 36

- vừa được xem lúc

Blog#176: 💪The Power of JavaScript Functional Programming🚀

. The main goal of this article is to help you improve your English level. I will use Simple English to introduce to you the concepts related to software development.

0 0 28

- vừa được xem lúc

[Javascript] Nâng cấp kỹ thuật tạo Tham số trong Hàm JS

1. Khái niệm.

0 0 24