1. Chào mừng bạn
Trong lớp học này, bạn sẽ lấy một ứng dụng web hiện có và thêm web worker để chia sẻ trạng thái giữa 2 cửa sổ đang mở. Đây là lớp học lập trình thứ tám trong loạt lớp học lập trình đi kèm cho hội thảo về Ứng dụng web tiến bộ. Lớp học lập trình trước đây là Service Worker Includes. Đây là lớp học lập trình cuối cùng trong loạt lớp học lập trình này.
Kiến thức bạn sẽ học được
- Thêm một worker dùng chung giữa nhiều cửa sổ đang mở
- Sử dụng Comlink để giúp bạn dễ dàng làm việc với các worker hơn
Những điều bạn cần biết
- JavaScript
Bạn cần có
- Một trình duyệt hỗ trợ shared web worker
2. Bắt đầu thiết lập
Bắt đầu bằng cách sao chép hoặc tải mã khởi đầu cần thiết để hoàn tất lớp học lập trình này:
Nếu bạn sao chép repo, hãy đảm bảo rằng bạn đang ở nhánh pwa06--working-with-workers
. Tệp zip cũng chứa mã cho nhánh đó.
Cơ sở mã này yêu cầu Node.js 14 trở lên. Sau khi có mã, hãy chạy npm ci
từ dòng lệnh trong thư mục mã để cài đặt tất cả các phần phụ thuộc mà bạn sẽ cần. Sau đó, hãy chạy npm start
để khởi động máy chủ phát triển cho lớp học lập trình.
Tệp README.md
của mã nguồn cung cấp nội dung giải thích cho tất cả các tệp được phân phối. Ngoài ra, sau đây là các tệp hiện có chính mà bạn sẽ sử dụng trong suốt lớp học lập trình này:
Tệp khoá
js/preview.js
– Tệp JavaScript của trang xem trướcjs/main.js
– Tệp JavaScript của ứng dụng chính
3. Viết một Worker
Hiện tại, chức năng xem trước của ứng dụng web chỉ cho thấy nội dung mới nhất khi tải. Lý tưởng nhất là ứng dụng sẽ cho thấy bản xem trước trực tiếp khi người dùng nhập. Việc này đòi hỏi bạn phải biên dịch một lượng lớn dữ liệu và chuyển dữ liệu đó giữa 2 cửa sổ đang mở. Vì lý do này, chúng ta không muốn thực hiện thao tác này trên luồng chính của bất kỳ cửa sổ nào đang mở. Thay vào đó, hãy sử dụng một web worker dùng chung.
Để bắt đầu, hãy tạo một tệp js/worker.js
bằng đoạn mã sau:
import { expose } from 'comlink';
import { marked } from 'marked';
class Compiler {
state = {
raw: '',
compiled: '',
};
subscribers = [];
async set(content) {
this.state = {
raw: content,
compiled: marked(content),
};
await Promise.all(this.subscribers.map((s) => s(this.state)));
}
subscribe(cb) {
this.subscribers.push(cb);
}
}
const compiler = new Compiler();
onconnect = (e) => expose(compiler, e.ports[0]);
Giải thích
Mã này thiết lập một lớp có tên là Compiler
, cho phép đặt nội dung và cho phép gọi các lượt đăng ký sau khi nội dung đó được biên dịch. Vì đây là một worker dùng chung, nên chỉ có một thực thể của lớp này được dùng, do đó, một thực thể mới của Compiler
sẽ được khởi tạo. Sau đó, để việc tương tác với lớp này diễn ra liền mạch từ bên ngoài worker, Comlink được dùng để hiển thị thực thể trình biên dịch, cho phép chúng ta sử dụng tất cả các phương thức trên thực thể này như thể thực thể đó được khai báo trong mã bằng cách sử dụng thực thể đó. Vì đây là một worker dùng chung thay vì một worker chuyên dụng, nên worker này cần được cung cấp cho tất cả các kết nối.
4. Gửi nội dung đến Worker
Sau khi tạo worker, chúng ta cần gửi nội dung vào worker đó. Để làm như vậy, hãy cập nhật js/main.js
để thực hiện những việc sau:
- Nhập hàm xuất đã đặt tên
wrap
từcomlink
- Tạo một Shared Worker mới có kiểu mô-đun tên là
worker
, đặt kiểu của Shared Worker này thànhmodule
và trỏ đến Shared Worker đó bằng mẫunew URL
(new URL('./worker.js', import.meta.url)
) - Tạo một biến
compiler
wrap
worker.port
- Trong hàm cập nhật của trình chỉnh sửa (
editor.onUpdate
), sau khi lưu nội dung vào cơ sở dữ liệu, hãy đợicompiler.set
hoàn tất, truyền nội dung vào
Giải thích
Việc bao bọc một mục xuất Comlink cho phép sử dụng những thứ như các phương thức lớp được hiển thị như thể chúng không được chia sẻ trên ranh giới của worker, ngoại trừ việc giờ đây mọi thứ đều không đồng bộ. Vì đây là một worker dùng chung thay vì một worker chuyên dụng, nên Comlink cần bao bọc cổng của worker thay vì chính worker đó. Giờ đây, bất cứ khi nào có nội dung cập nhật cho trình chỉnh sửa, nội dung đó sẽ được gửi vào worker để xử lý!
5. Cập nhật Trang xem trước
Bước cuối cùng là lấy nội dung đã biên dịch ra khỏi worker dùng chung vào bản xem trước! Quy trình thiết lập để thực hiện việc này phần lớn là giống nhau, nhưng vì các hàm không thể truyền giữa ranh giới của worker, nên bạn cần sử dụng một proxy cho hàm thay thế. Comlink luôn sẵn sàng trợ giúp. Cập nhật js/preview.js
để thực hiện những việc sau:
- Nhập các hàm xuất được đặt tên
wrap
vàproxy
từcomlink
- Tạo và bao bọc worker dùng chung như bạn đã làm trong
js/main.js
- Gọi phương thức
subscribe
của trình biên dịch bằng một hàm proxy đặt thuộc tínhcompiled
của dữ liệu đến thành HTML bên trong của vùng xem trước
Sau khi hoàn tất, hãy mở bản xem trước, bắt đầu nhập trong trình chỉnh sửa và bạn sẽ thấy thú vị và hào hứng khi xem markdown tự động biên dịch và xuất hiện theo thời gian thực trong vùng xem trước mà không chặn luồng chính của trang nào!
6. Xin chúc mừng!
Bạn đã tìm hiểu cách sử dụng worker dùng chung để chia sẻ trạng thái giữa nhiều phiên bản PWA.