Web Worker trong HTML5

JavaScript được thiết kế để chạy trong một môi trường single-threaded, nghĩa là nhiều script không thể chạy tại cùng một thời điểm. Giả sử một tình huống mà bạn cần xử lý các sự kiện UI, truy vấn, và xử lý một lượng lớn dữ liệu API, và thao tác DOM.

JavaScript sẽ treo trình duyệt của bạn trong tình huống mà sự sử dụng CPU là cao. Chúng ta có một ví dụ đơn giản mà Javascript phân tích một vòng lặp lớn:

<html>
<head>
<title>Big for loop</title>
  <script>
      function bigLoop(){
         for (var i = 0; i <= 10000000000; i += 1){
            var j = i;
         }
         alert("Completed " + j + "iterations" );
      }
      function sayHello(){
         alert("Hello sir...." );
      }
  </script>
</head>
<body>
   <input type="button" onclick="bigLoop();" value="Big Loop" />
   <input type="button" onclick="sayHello();" value="Xin chao!" />
</body>
</html>


Web Workers là gì?

Tình huống được giải thích ở trên có thể được giải quyết bởi sử dụng Web Workers mà sẽ làm tất cả các task tính toán đắt đỏ mà không cần ngắt giao diện người dùng và đặc biệt chạy trên các thread riêng rẽ.

Web Workers cho phép các script có thời gian chạy dài mà không bị ngắt bởi các script mà phản hồi tới các cú nhấp chuột hoặc các tương tác người dùng khác, và cho phép các task dài được thực thi mà không cần phải giữ tính phản hồi của trang.

Web Workers là script nền tảng và chúng tương đối nặng, và không được dự định để được sử dụng với số lượng lớn. Ví dụ, nó là không thích hợp để chạy một Worker cho mỗi pixel của một hình ảnh 4 megapixel.

Khi một script đang thực thi bên trong một Web Worker, nó không thể truy cập đối tượng cửa sổ trang web (window.document), nghĩa rằng Web Workers không có sự truy cập trực tiếp tới trang web và DOM API. Mặc dù Web Worker không thể đóng khối UI trình duyệt, chúng có thể vẫn sử dụng CPU và làm cho hệ thống kém phản hồi hơn.

Cách Web Workers làm việc?

Web Workers được khởi tạo với URL của một JavaScript file, chứa code mà Worker sẽ thực thi. Code này thiết lập Event Listeners và giao tiếp với script mà sinh ra nó từ trang chủ. Sau đây là cú pháp đơn giản:

var worker = new Worker('bigLoop.js');

Nếu javascript file đã xác định tồn tại, trình duyệt sẽ tạo một Worker Thread mới, mà được tải không đồng bộ. Nếu đường truyền tới Worker của bạn trả về một 404, Worker sẽ thất bại.

Nếu ứng dụng của bạn có nhiều file hỗ trợ javascript, bạn có thể nhập chúng với phương thức importScript() mà nhận tên file như là tham số, được phân biệt nhau bởi dấu phảy như sau:

importScripts("helper.js", "anotherHelper.js");

Một khi Web Worker được tạo ra, giao tiếp giữa Web Worker và trang mẹ của nó được thực hiện bởi sử dụng phương thức postMessage(). Phụ thuộc vào trình duyệt/phiên bản của bạn, postMessage() có thể chấp nhận hoặc một chuỗi hoặc đối tượng JSON như là một tham số của nó.

Thông báo được truyền bởi Web Worker được truy cập sử dụng sự kiện onmessage trong trang chính. Bây giờ chúng ta viết ví dụ vòng lặp lớn của chúng ta bởi sử dụng Web Worker. Trang chính là hello.htm mà sẽ tạo một Web Worker để thực thi vòng lặp và để trả về giá trị cuối cùng của biến j:

html>
<head>
<title>Big for loop</title>
  <script>
      var worker = new Worker('bigLoop.js');
      worker.onmessage = function (event) {
        alert("Completed " + event.data + "iterations" );
      };


      function sayHello(){
         alert("Hello sir...." );
      }
  </script>
</head>
<body>
   <input type="button" onclick="sayHello();" value="Xin chao!"/>
</body>
</html>

Sau đây là nội dung của bigLoop.js file. Điều này sử dụng postMessage() API để truyền giao tiếp trở lại trang chính:

for (var i = 0; i <= 1000000000; i += 1){
   var j = i;
}
postMessage(j);

Bây giờ chúng ta giữ hello.htm và bigLoop.js file trong cùng một thư mục và thử truy cập hello.htm bởi sử dụng phiên bản mới nhất của Safari hoặc Firefox.

Dừng Web Workers

Web Workers không tự dừng, nhưng trang mà bắt đầu chúng có thể dừng chúng bởi gọi phương thức terminate().

worker.terminate();

Một Web Worker bị dừng sẽ không bao giờ phản hồi các thông báo hoặc thực hiện bất kỳ kỹ thuật tính toán bổ sung nào. Bạn không thể bắt đầu lại một Worker; thay vào đó bạn có thể tạo một Worker mới sử dụng cùng URL đó.

Xử lý các lỗi

Ví dụ sau về một hàm xử lý lỗi trong Web Worker JavaScript file mà log các lỗi tới bàn kiểm soát. Với code xử lý lỗi, ví dụ trên sẽ trở thành như sau:

<html>
<head>
<title>Big for loop</title>
  <script>
      var worker = new Worker('bigLoop.js');
      worker.onmessage = function (event) {
        alert("Completed " + event.data + "iterations" );
      };


      worker.onerror = function (event) {
         console.log(event.message, event);
      };


      function sayHello(){
         alert("Hello sir...." );
      }
  </script>
</head>
<body>
   <input type="button" onclick="sayHello();" value="Xin chao!"/>
</body>
</html>

Kiểm tra trình duyệt hỗ trợ

Sau đây là cú pháp để kiểm tra một sự hỗ trợ tính năng Web Worker có sẵn trong một trình duyệt:

<html>
<head>
<title>Big for loop</title>
  <script src="./src/modernizr-1.5.min.js"></script>
  <script>
   if (Modernizr.webworkers) {
      alert("Congratulation!! you have web workers support." );
   }else{
      alert("Sorry!! you do not have web workers support." );
   }
  </script>
</head>
<body>
   <p>Checking for Browser Support for web workers</p>
</body>
</html>

Bình luận