Làm cách nào để tạo đa luồng JavaScript?

Có nhiều vấn đề liên quan đến hành vi đơn luồng của JavaScript. Trong số đó là kết hợp đồng thời các tác vụ chạy dài với các thành phần giao diện người dùng. Sự cố được đánh dấu có thể gây ra lỗ hổng lớn trong ứng dụng web của chúng tôi khi tác vụ sử dụng nhiều CPU chặn các thành phần giao diện người dùng, khiến trang web bị treo

Thông thường, các nhà phát triển sử dụng hàm setTimeout và kiến ​​trúc hướng sự kiện để bắt chước đồng thời. Ngay cả hàm

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
2 cũng không phải là một phần của các tính năng JavaScript; . js hoặc trình duyệt. Họ cung cấp
//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
2 thông qua các API dành riêng cho môi trường. Bằng cách này, chúng tôi chỉ thay đổi hành vi đồng bộ thành hành vi không đồng bộ. Do đó, ý tưởng về kiến ​​trúc đa luồng trở nên rất hữu ích và HTML5 cung cấp cho nhân viên web thông số kỹ thuật như một giải pháp thay thế tuyệt vời

Bài viết này mô tả các sự cố với hoạt động đơn luồng và cách triển khai, chẳng hạn như tính song song/đồng thời, để giảm bớt các sự cố này bằng cách sử dụng API Công nhân web

Nhân tiện—mã nguồn của dự án này có trên GitHub

Kịch bản. hoạt động chặn

Tương tự như cách một đứa trẻ kêu cứu, một lỗi xuất hiện trong trình duyệt của chúng ta và chúng ta thấy mình bất lực; . Do đó, tất cả các nút vẫn không thể nhấp được và giao diện người dùng không phản hồi, dẫn đến cửa sổ bật lên không mong muốn

Một trong những sai sót của ứng dụng đơn luồng xuất hiện từ việc xây dựng một ứng dụng nặng sử dụng nhiều CPU. Các ví dụ bao gồm xử lý các mảng lớn, I/O nền và hiển thị một lượng lớn dữ liệu từ máy chủ. Khi chúng tôi thấy một chức năng thực thi cản trở chức năng sau thực thi trong vài giây, hãy đợi vì một luồng đơn lẻ đang xử lý một quy trình chặn

Ở phần sau của bài viết này, chúng tôi sẽ tạo ra lỗi này và khắc phục nó bằng những gì chúng tôi học được ở đây

JavaScript đơn luồng

Máy ảo JavaScript về cơ bản được thiết kế để sinh ra một luồng duy nhất, điều đó có nghĩa là nó không thể đọc và thực thi đồng thời nhiều lệnh. Do đó, nó phải đợi việc thực hiện một lệnh duy nhất hoàn tất trước khi chuyển sang lệnh tiếp theo. Điều này còn được gọi là lập trình đồng bộ hoặc hành vi chặn

Sau khi đã xác định được các vấn đề, hãy cùng tìm hiểu cách người lao động có thể giảm bớt căng thẳng cho chúng ta

Chúng tôi có một thao tác I/O nền mở rộng để chạy từ máy chủ và quá trình này sẽ mất thêm vài giây. Sau đó, chúng tôi phải nghĩ ra một phương tiện để xử lý các hành động của máy chủ trên một luồng khác để giao diện người dùng của chúng tôi ở trạng thái sạch

Chuỗi độc lập mới sẽ chạy hành động chạy dài để chuỗi chính của chúng tôi có không gian trống để thực hiện các hướng dẫn khác. Nếu không, ứng dụng của chúng ta sẽ trở nên chậm hơn, dẫn đến trải nghiệm người dùng không tốt

Công nhân web là gì?

Nhân viên web cho phép hai hoặc nhiều luồng dưới dạng hai tập lệnh độc lập thực hiện đồng thời nhiều tác vụ. Tất cả các đơn vị thực thi bên ngoài kernel được tổ chức thành các process và thread. Công nhân web cho phép chúng tôi sinh ra một phiên bản mới của công cụ JavaScript

Tương tự, đồng thời và song song mô tả các tác vụ chúng ta có thể thực hiện với nhân viên web;

song song

Tính song song là khi nhân viên web tạo ra hai hoặc nhiều tác vụ đồng thời xảy ra bằng cách sử dụng hai hoặc nhiều lõi CPU. Tuy nhiên, web worker không tự động cung cấp Parallelism. Thay vào đó, đó là đặc điểm kỹ thuật của phần cứng hệ thống của chúng tôi, bằng cách có nhiều lõi CPU và bộ lập lịch được gắn vào lõi phải quyết định chạy các luồng trên các lõi CPU riêng biệt. Ngược lại, đồng thời là quá trình đa nhiệm trên một lõi CPU bằng cách xen kẽ giữa các tác vụ

Khi máy ảo JavaScript hiển thị hoạt ảnh của chúng tôi và các thành phần giao diện người dùng trên luồng của nó, phiên bản web worker sẽ tạo luồng của nó trên một lõi riêng biệt trong nền, thực hiện các tác vụ khác cho phép ứng dụng của chúng tôi chạy nhiều tác vụ cùng một lúc, chẳng hạn như nhấp, chọn . Các tay trống khác nhau hoàn thành nhiệm vụ tạo nhịp. Nhân viên web có thể tạo tính toán song song [bằng cách hoàn thành đồng thời nhiều tác vụ] nếu có sẵn CPU và phần cứng cần thiết

nguồn hình ảnh. đây

đồng thời

Việc triển khai nhân viên web trên một lõi đơn tương tự như kịch bản này. Quá trình chuyển đổi diễn ra rất nhanh nên không gây chú ý và một phần do nhân và phần cứng CPU kết hợp với nhau. Thiết kế ứng dụng của chúng tôi đủ linh hoạt để luân phiên giữa các tác vụ A và B, cũng như B và C, là những gì chúng tôi đang cố gắng đạt được với đồng thời. Khi chúng tôi đạt được điều này, giao diện người dùng của chúng tôi miễn phí

Đối với đồng thời, điều này nghe có vẻ phức tạp, nhưng hãy biết rằng các tác vụ không xảy ra đồng thời mà thực hiện xen kẽ cho đến khi toàn bộ tác vụ hoàn thành. Tuy nhiên, nó cho phép đa nhiệm. Với hình dưới đây, chúng ta có thể dễ dàng nhớ đồng thời làm gì

Nguồn. đây

Ví dụ về tính toán CPU nặng

Không phải tất cả các vấn đề đều yêu cầu sử dụng web worker, nhưng tính toán nặng và các tác vụ kéo dài là một số điều kiện bắt buộc phải sử dụng web worker, bao gồm những điều sau

  • Mã hóa và giải mã dữ liệu của một chuỗi lớn
  • Tính toán toán học, chẳng hạn như tìm tất cả các số nguyên tố trong một số lớn
  • Hoạt động đầu vào và đầu ra nền tảng hoặc dữ liệu chuyên sâu

Các vấn đề có thể xảy ra nếu không được quản lý tốt

  • Trải nghiệm người dùng không tốt do hoạt động chặn
  • Ứng dụng web trở nên rất chậm và thường bị đóng băng

Một chức năng chạy lâu sẽ đóng băng giao diện người dùng. Do đó, các phần khác của trang buộc phải chờ hoàn thành. Do đó, nó làm cho trang, nút và các tính năng khác không sử dụng được

Giới thiệu Web Worker

Hãy đi sâu vào một số khía cạnh cơ bản của nhân viên web. Chúng tôi sẽ ghép các mảnh lại với nhau trong phần sau và sinh ra công nhân cho các dự án demo đơn giản của chúng tôi. Nếu bạn đã quen thuộc với các khái niệm cơ bản, hãy bỏ qua phần này

Cách tạo đối tượng Web Worker

Vì nhân viên web độc lập với luồng/tập lệnh chính, nên chúng tôi tạo một tệp riêng cho các đoạn mã của nó. Bên dưới, hàm tạo của nó tải tập lệnh nằm ở "worker. js" và thực thi nó trong nền. Nếu không tìm thấy tập lệnh, công nhân sẽ âm thầm thất bại;

Tạo đối tượng worker

//main.js
let worker = new Worker["worker.js"];

Tiếp theo, chúng tôi muốn công nhân của mình giao tiếp với tệp JavaScript của chúng tôi để tạo điều kiện trao đổi dữ liệu giữa hai luồng độc lập

Tìm bên dưới các loại dữ liệu có thể lưu chuyển giữa chúng

Gửi tin nhắn giữa các chủ đề

Chúng tôi có thể gửi dữ liệu qua lại giữa ứng dụng chính và tập lệnh worker của chúng tôi. Gọi hàm

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
4 đảm bảo giao tiếp chéo giữa hai tay. Do đó, chúng tôi không cần phải có cùng một máy chủ, giao thức hoặc cổng để gửi tin nhắn cho bên khác. Chúng tôi có thể gửi loại dữ liệu sau dưới dạng tin nhắn. JSON, Chuỗi, số và mảng

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.

//worker.js
postMessage["hi from worker"]; // Send this back to the main script.

Nhận tin nhắn đã đăng

Chúng tôi cần thêm trình lắng nghe sự kiện vào cả hai bên để nhận các thông báo trên. Chúng tôi có thể sử dụng

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
5 hoặc addEventListener

//worker.js
self.addEventListener['message', function[e] {
  // Send the message back.
  self.postMessage['You said: ' + e.data];
}, false];

Lưu ý rằng chúng tôi sử dụng self cho worker để cung cấp tham chiếu toàn cầu cho web worker vì nó không phải là đối tượng cửa sổ

Người nghe sự kiện trong tập lệnh chính

________số 8

Chấm dứt một công nhân

Chúng ta có thể hủy nhiệm vụ của worker bằng cách sử dụng hàm

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
6 hoặc để nó tự kết thúc bằng cách tự gọi hàm
//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
7. Điều này giúp giảm mức tiêu thụ bộ nhớ cho các ứng dụng khác trên máy tính của người dùng

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
1

Nhập tập lệnh bên ngoài

Chúng ta có thể nhập thư viện hoặc tệp vào worker bằng hàm

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
8. Hàm này chấp nhận số không hoặc bất kỳ số lượng tên tệp nào

Ví dụ này tải script1. js và script2. js vào công nhân. người làm việc. js

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
3

Ví dụ về công nhân web đơn giản đang hoạt động

Dự án mẫu này sẽ làm sáng tỏ hơn về việc làm cho hai tập lệnh thực hiện đồng thời. Một người nhận dữ liệu và gửi chúng cho người kia. Thứ hai xử lý nó và gửi nó trở lại. Đây là liên kết đến mã nguồn cho dự án này trên repo GitHub của tôi

Có ba tập tin

  • Một tệp HTML
  • Một kịch bản công nhân
  • Một tập lệnh JavaScript

Kịch bản. js bên dưới sẽ gửi hai số đến luồng của worker qua postMessage

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
4

Đây là tập lệnh công nhân của chúng tôi;

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
5

Công nhân web và xây dựng các ứng dụng sử dụng nhiều CPU đang hoạt động

Trong phần này, chúng ta sẽ làm như sau

  • Tạo phản hồi web để hiển thị một tác vụ sử dụng nhiều CPU hoặc chạy lâu trên một luồng

  • Sử dụng nhân viên web để giải quyết vấn đề bằng cách tạo đa luồng

Tác dụng phụ của việc chạy các tác vụ sử dụng nhiều CPU trên một luồng đơn

Trong phần này, chúng tôi sẽ tạo ra một hiệu ứng bất lợi đơn giản của hoạt động đơn luồng trên một trang web. Đây là liên kết đến mã nguồn cho dự án này

Tạo tệp JavaScript và chèn đoạn mã bên dưới. Chúng tôi đang lặp qua một số lượng lớn; . Mọi nỗ lực nhấp vào bất kỳ nút nào khác trên giao diện người dùng sẽ đóng băng ứng dụng và chúng tôi sẽ nhận được phản hồi hiển thị bên dưới. Điều này tương tự như việc tìm nạp một khối dữ liệu lớn hơn từ máy chủ một cách đồng bộ

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
6

Giải quyết vấn đề được mô tả ở trên với Web Worker

Thêm tệp của worker, tạo hàm tạo của nó trong luồng chính và sử dụng tên tập lệnh làm đối số. Điều này bổ sung thêm nhiều tính năng hơn cho HTML để nó có thể năng động hơn. Cuối cùng, chúng tôi có một cái gì đó với giao diện người dùng bên dưới

Trong tập lệnh chính, chúng tôi sử dụng phương pháp

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
6 để hủy hoạt động của công nhân

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
0

Trong kịch bản công nhân, chúng tôi sử dụng self để chỉ công nhân. Chúng tôi sử dụng phương pháp ____50 để kết thúc kết nối của công nhân. Điều cực kỳ quan trọng là chúng tôi phải đóng kết nối khi hoạt động của công nhân hoàn tất

//main.js
worker.postMessage["hello world"]; // Send this to the worker script.
1

Phần kết luận

Có nhiều điều tuyệt vời hơn mà chúng ta có thể làm với nhân viên web, ngoài những gì đã trình bày ở đây; . Bài viết này đã cung cấp đủ thông tin chi tiết và ví dụ để người đọc xác định loại vấn đề nào chúng ta có thể sử dụng nhân viên web và những gì chúng ta đang cố gắng đạt được [đồng thời và song song] khi sử dụng chúng

Bạn có thể tạo JavaScript đa luồng không?

js đã giới thiệu mô-đun worker-threads, cho phép bạn tạo các luồng và thực thi song song nhiều tác vụ JavaScript. Khi một luồng hoàn thành một tác vụ, nó sẽ gửi một thông báo đến luồng chính chứa kết quả của thao tác để nó có thể được sử dụng với các phần khác của mã

Tại sao JavaScript không đa luồng?

Bởi vì JavaScript là ngôn ngữ kịch bản được thiết kế để giải quyết mối quan tâm của một người dùng trên một giao diện người dùng; . Đa luồng đơn giản là không cần thiết ở đây. Nếu bạn muốn đa luồng, thì có lẽ bạn muốn xử lý một tác vụ tính toán dài. . Multi threading is simply not required here. If you want multi-threading, then you probably want to process a computationally long task.

JavaScript đơn hay đa luồng?

Trong bối cảnh lập trình, Parallelism là việc sử dụng nhiều luồng trong một hệ điều hành. Các quy trình có thể chạy cùng lúc bất kể thứ tự thực hiện. Tuy nhiên, JavaScript là luồng đơn và chỉ một dòng mã có thể được thực thi tại bất kỳ thời điểm nào.

Chủ Đề