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

Web Worker - Anh công nhân thầm lặng trong ứng dụng của bạn

0 0 211

Người đăng: Nguyen Quang Phu

Theo Viblo Asia

Như mọi người cũng đã biết thì Javascript là một ngôn ngữ đơn luồng, các đoạn code hầu như không thể chạy song song. Một website có đến hàng tá các chức năng, thao tác cần phải thực hiện, khi ứng dụng của bạn đang xử lý một đoạn code, thì bạn không thể làm gì khác ngoài cách ngồi đợi nó xử lý.

Thế nên là các lập trình viên thường sử dụng bất đồng bộ như setTimeout, setInterval hay XMLHttpRequest. Ví dụ đơn giản khi chúng ta sử dụng AJAX cần chuyền vào một callback để thực thi code sau khi có response, nếu như việc xử lý đơn giản, không phức tạp, tốn ít thời gian thì sẽ không có chuyện gì xảy ra. Thế nhưng nếu việc xử lý tốn nhiều thời gian ngốn nhiều CPU thì rất dễ xảy ra việc crash app, đối với người dùng thì đây quả là một trải nghiệm không hề vui vẻ

Trong bài này mình sẽ giới thiệu cho các bạn một Web APIs để thực hiện multi-threading task khá tốt đó chính là Web Worker.

Web Worker

1. Web Worker là gì ?

Web Worker là một đối tượng trong Javascript được tạo ra bởi các hàm contructor như Worker, SharedWorker... với tham số được truyền vào là một file JS chứa các đoạn code sẽ được thực thi bởi Worker. Các script được viết trong file này sẽ được thực thi ngầm, không ảnh hưởng đến trải nghiệm của người dùng. Vì vậy với các tác vụ tốn nhiều thời gian các bạn có thể dùng Worker để xử lý.

Đây là một kiến trúc hoạt động cơ bản của Worker với 2 luồng chính đó là main thread (main.js) và worker(worker.js). Nhìn trong ảnh chúng ta có thể hình dung được cơ chế hoạt động qua lại giữa hai luồng là đều có thể trao đổi thông tin với nhau.

Ví dụ việc gọi API ban đầu tốn nhiều thời gian main thread có thể chuyển xuống cho worker xử lý, sau khi xử lý xong thì chuyển lại dữ liệu cho main.js.

Cả main thread và worker đều giao tiếp vào gửi dữ liệu cho nhau thông qua hàm postMessage(), và sử dụng hàm onmessage() để lắng nghe dữ liệu được gửi tới. Dữ liệu được gửi qua lại giữa hai tiến trình này là một bản sao chép.

Web Worker không phải của Javascript, mà đây là một tính năng của trình duyệt cho phép chúng ta truy xuất qua Javascript

2. Dedicated workers

Dedicated workers chỉ có thể truy cập bởi đoạn script gọi đến nó.

Để kiểm tra trình duyệt của chúng ta hỗ trợ Web Worker hay không sử dụng

if (window.Worker) { ....
}

Khởi tạo một Worker

Để khởi tạo mội Web Worker rất đơn giản, chỉ cần sử dụng Worker constructor(), truyền bên trong constructor này là một đường dẫn tới file xử lý ngầm bởi Worker

var myWorker = new Worker('my-worker.js');

Gửi và nhận message trong Web Worker

Như mình có nói ở trên Worker và main thread sẽ giao tiếp với nhau thông qua hai hàm chính là postMessage()onmessage(). Cả main thread và Worker đều nhận thông tin thông qua sự kiện onmessage() và truy cập dự liệu thông qua event.data.

Ví dụ

<button onclick="startWorker()">Start Worker</button>
<button onclick="stopWorker()">Stop Worker</button>
const worker = new Worker("worker.js"); // gửi dữ liệu đến Worker xử lý
worker.postMessage("Tin nhắn này gửi đến worker") //nhận tin nhắn từ Worker
worker.onmessage = function(e) { console.log(e.data); // Tin nhắn này gửi đến main thread
}

Khi gửi message đến Worker, để nhận được dữ liệu sử dụng sự kiện onmessage để lắng nghe

self.onmessage = function (e) { console.log(e.data); // Tin nhắn này gửi đến worker // gửi tin nhắn sang main thread self.postMessage("Tin nhắn này gửi đến main thread");
}

Trong onmessage handler cho phép chúng ta xử lý dữ liệu nhận được từ main thread mà không làm ảnh hưởng tới giá trị tại main thread vì dữ liệu được nhận là bản sao chép chứ không phải dữ liệu gốc.

Trong thread chính onmessagepostMessage cần phải được gọi bởi worker tương ứng, còn trong worker không cần phải khai báo rõ ràng chỉ cần gọi thông qua từ khóa this hoặc self là được vì trong một thread có thể có nhiều worker, nhưng một worker chỉ có thể quản lý bới một thread

Ngừng Worker đang được thực thi

Nếu muốn dừng một Worker đang chạy chúng ta có 2 cách

  • Sử dụng phương thức terminate() trên thực thể Worker
  • Sử dụng phương thưc close() bên trong file Worker
worker.terminate();

hoặc

self.close()

Xử lý ngoại lệ

Khi code việc xử lý ngoại lệ là không thể thiếu và Web Worker cũng vậy. Trong quá trình chạy worker nếu có lỗi xảy ra onerror handler sẽ được gọi tới thông qua sự kiện error.

worker.addEventListener('error', function (e) { console.log(e)
}, false)

Event error cung cấp cho chúng ta một vài thuộc tính để xác định được thông tin lỗi khá hữu ích

  • message: mô tả chi tiết của lỗi
  • filename : file xảy ra lỗi
  • lineno: dòng xảy ra lỗi

Import script và libraries

Bên trong các file Worker cho phép chúng ta import thêm các file script hoặc các libraries thông qua hàm importScripts

importScripts('foo.js'); /* imports file "foo.js" */
importScripts('foo.js', 'bar.js'); /* imports nhiều file */

Sau khi import, trình duyệt sẽ load từng file một và thực hiện các đoạn code bên trong script đó, nếu một script không được load thì sẽ sinh ra một exception là NETWORK_ERROR => các đoạn code phía dưới sẽ không được thực thi.

Web Worker sẽ không hoạt động nếu chúng ta truy cập trực tiếp các web page từ filesystem, nếu muốn sử dụng worker thì cần có một server để chạy nó nhé các pạn

3. Shared Worker

Khác với Dedicated Worker thì Shared Worker có thể được truy cập từ nhiều đoạn script nào đó miễn là trong cùng một domain hay là cùng protocol, port, host.

Khởi tạo một Shared Worker

Tạo một Shared Worker cũng đơn giản như tạo một Worker bình thường chỉ khác là chúng ta sẽ sử dụng Shared Worker object thay vì Worker object

var worker = new SharedWorker("worker.js");

Tương tác với một Shared Worker

Bất cứ một file script nào trong cùng một domain đều có thể gọi tới Shared Worker thông qua MessagePort object được tạo bởi thuộc tính port thuộc SharedWorker interface.

Việc gửi và nhận message từ các file script khác tới Shared Worker phức tạp hơn một chút khi chúng cần thông qua object port.

var worker = new SharedWorker("worker.js"); // lắng nghe message được truyền đến
worker.port.addEventListener("message", function(e) { alert(e.data);
}, false); // Gửi message 
worker.port.postMessage("Tin nhắn này được gửi đến shared worker");

Để lắng nghe được message được gửi đến từ main thread thì ở file shared worker cần phải sử dụng onconnect handler để kết nối với port. Các ports được kết nói với worker được truy cập thông qua thuộc tính ports.

onconnect sẽ được kích hoạt khi kết nối được mở giữa Shared Workermain thread qua MessagePort object. Sau đó các công việc khác như lắng nghe và gửi message trở lại cho main thread cũng giống như cách chúng ta làm với Dedicated Worker.

onconnect = function(e) { var port = e.ports[0]; port.addEventListener('message', function(e) { var workerResult = 'Result: ' + e.data; port.postMessage('Tin nhắn từ shared worker tới main thread'); }); port.start(); // Required when using addEventListener
}

Nếu sử dụng addEventListener để lắng nghe message event thì cần phải thêm port.start() ở cuối bên trong onconnect event.

4. Kết luận

Trên đây là những chia sẻ của mình về Web Worker, nếu trong bài có nhầm lẫn hay có gì chưa hiểu thì các bạn hãy comment phía dưới để chúng ta cùng trao đổi kiến thức nhé.

Nếu bài viết hữu ích hãy tặng mình 1 like, 1 clip và 1 subcribe nhé ????

Bình luận

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

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

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 500

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

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414

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

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 136

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

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 117

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

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 93

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

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 229