Если вы использовали Javascript, вы, возможно, знаете, что это однопоточный язык сценариев, который работает в файлах HTML. Это означает, что одновременно выполняется только один оператор.
Однако мы также знаем, что JS имеет асинхронное поведение, с помощью которого мы можем добиться параллелизма. Но Асинхронность не является многопоточной, так как она также зависит от одного потока. В какой-то степени даже асинхронные операции блокируют рендеринг DOM в браузере.
Многопоточность позволяет обрабатывать несколько потоков одновременно, а не несколько процессов. Включив многопоточность, программы могут выполнять несколько операций одновременно.
Итак, как добиться многопоточности в JS?
Ответ — Web Workers! В JavaScript вы можете использовать параллельное программирование для одновременного выполнения нескольких операций с помощью веб-воркеров.
Один из способов думать о веб-воркерах — это фрагменты кода, которые представляют собой ресурсоемкие задачи, выполнение которых занимает много времени. Мы передаем эту дорогостоящую логику браузеру для выполнения в фоновом режиме (отдельный поток). Поскольку он работает в фоновом режиме, он не влияет на JavaScript в основном потоке, отвечающем за веб-страницу.
Веб-воркеры — это код JavaScript, который выполняется в отдельном потоке без прямого доступа к DOM.
Однако веб-воркеры не полностью изолированы от основного потока. Когда рабочему потоку необходимо связаться с основным потоком, он может отправить сообщение, а основной поток может отправить сообщение самостоятельно в качестве ответа.
Как использовать веб-воркеров в JavaScript
Для создания нового рабочего процесса мы используем конструктор Worker()
, указав URI скрипта для выполнения в рабочем потоке в файле main.js.
Рабочий код должен находиться в отдельном файле, в данном случае worker.js, который мы можем использовать для создания отдельного рабочего потока с помощью конструктора Worker
и передачи его пути к файлу. .
// main.js
if (window.Worker) {
const myWorker = new Worker('worker.js');
} else {
console.log('Your browser doesn't support web workers');
}
Отправка и получение сообщений от выделенного работника может быть достигнуто с помощью метода postMessage()
и обработчика событий onmessage
. Тип данных сообщения может быть строкой, числом, логическим значением, массивом, объектом, нулевым значением или неопределенным. Данные всегда передаются по значению и сериализуются, а затем десериализуются в процессе связи.
Вы можете передать только один аргумент в postMessage
. Если вы хотите передать несколько аргументов, используйте вместо них object
.
// main.js // To receive the message from workermyWorker.onmessage = (event) => {
var message =event
.data; ...};
ORmyWorker
.addEventListener('message', function(event) { var message =event
.data; ... }); -------- // To post a message to workermyWorker
.postMessage('Posting a new message');
Теперь, чтобы рабочий процесс услышал сообщение, нам нужно установить прослушиватель событий в файле worker.js для события сообщения.
// worker.js // To receive message from main thread self.addEventListener('message', function(event) { // message received from main thread var message = event.data; ... // To post a message to main thread self.postMessage("message received"); }); OR self.onmessage = (event) => {
var message =event
.data; ... // To post a message to main thread self.postMessage("message received");};
Любые логические ошибки, вызванные данными, переданными сценарием, могут быть обнаружены с помощью обработчика событий onerror
.
// main.js
myWorker.onerror = function(event) {
console.log("Error in file: "+event.filename+");
console.log("Error in Line number: "+event.lineno+");
console.log("Error Description: "+event.message+");
};
Рабочий веб-поток можно остановить с помощью метода close()
.
// worker.js self.addEventListener('message', function(event
) { var message =event
.data; self.postMessage('message received'); self.close(); // Closing the thread });
Пункты, которые следует отметить
- Данные, которыми обмениваются основной поток и рабочие потоки, копируются, а не совместно используются.
- Вы не можете обновлять DOM из рабочего потока, поскольку они выполняются в отдельном контексте от главного окна.
- Рабочие не имеют доступа к объектам
window
иdocument
, но у них есть доступ к некоторым возможностям объектаwindow
, таким какWebsockets
иindexedDB.
. Кроме того, он может получить доступ кLocation
,AppCache
. - Сценарий должен обслуживаться с того же хоста или домена из соображений безопасности, и по этой же причине веб-воркеры не будут работать, если мы откроем файл локально по схеме
file://
.
Варианты использования веб-воркеров
Любые интенсивные вычисления ЦП, которые блокируют основной поток пользовательского интерфейса, могут быть выгружены на Web Worker. Вот несколько вариантов использования рабочих:
- Предварительная выборка и/или кэширование.
- Веб-ввод/вывод — опрос URL-адресов в фоновом режиме. Таким образом, вы не блокируете пользовательский интерфейс в ожидании результатов опроса.
- Обработка больших наборов данных или Обновление строк локальной веб-базы данных (
indexedDB
). - Рисование на холсте, фильтрация изображений и манипулирование изображениями.
- Подсветка синтаксиса кода или форматирование текста в реальном времени.
Заключение
Используя веб-воркеры, мы можем добиться параллельной обработки нескольких операций, освободив основной поток браузера от тяжелых вычислений, запустив рабочий скрипт в фоновом режиме (отдельный поток). Это идеальное решение, если приложение выполняет дорогостоящую логику в браузере, а также помогает достичь более высокой производительности приложения.