Вам когда-нибудь приходилось запускать код в браузере, который так долго запускал ваше приложение, которое на какое-то время переставало отвечать на запросы? С веб-воркерами HTML5 вам больше никогда не придется сталкиваться с этим.
Веб-воркеры позволяют отделить долго выполняющийся код и запускать его независимо от другого кода, работающего на странице. Благодаря этому ваш пользовательский интерфейс остается отзывчивым даже во время сложных операций.
Что такое веб-воркеры?
Традиционно JavaScript является однопоточным языком. Это означает, что ничто другое не может работать, пока работает один фрагмент кода. Например, если у вас есть код, пытающийся анимировать элемент DOM, код, пытающийся изменить переменную, должен дождаться окончания анимации, прежде чем он сможет запуститься.
Веб-воркеры — это файлы JavaScript, которые выполняются в отдельном потоке без прямого доступа к модели DOM.
Один из способов думать о веб-воркерах состоит в том, что они представляют собой фрагменты кода, выполнение которых занимает много времени, поэтому вы предоставляете их браузеру для выполнения в фоновом режиме. Поскольку этот код теперь работает в фоновом режиме, он не влияет на JavaScript, отвечающий за вашу веб-страницу.
В качестве побочного эффекта он больше не может напрямую взаимодействовать с остальной частью вашего кода, поэтому веб-воркеры не имеют доступа к DOM. Однако по-прежнему доступны многие другие API-интерфейсы браузера, включая API-интерфейсы WebSocket и Fetch.
Однако веб-воркеры не полностью изолированы от основного потока. Когда рабочему потоку необходимо связаться с основным потоком, он может отправить сообщение, а основной поток может отправить в ответ свое собственное сообщение.
Почему веб-воркеры?
До веб-воркеров единственным способом запуска JavaScript, который требовал много времени в браузере, был:
- Смиритесь с тем, что страница какое-то время не будет отвечать на запросы.
- Разбейте этот код на асинхронные фрагменты.
Поскольку страница, которая не отвечает, обычно плохо работает с пользователем, вы можете выбрать асинхронный вариант. Написание кода таким образом означает разделение его на более мелкие части, которые браузер может выполнять, пока он не обрабатывает пользовательский интерфейс. Части должны быть достаточно маленькими, чтобы, если пользовательский интерфейс нуждается в обновлении, браузер мог завершить выполнение текущей части и заняться пользовательским интерфейсом.
Веб-воркеры были добавлены в HTML5, чтобы предложить лучшее решение этой проблемы. Вместо того, чтобы заставлять вас проявлять творческий подход к асинхронному коду, они позволяют четко отделить функцию для запуска в отдельном изолированном потоке.
Это упростило разработчикам написание такого кода, а также улучшило взаимодействие с пользователем.
Примеры использования веб-воркеров
Любое приложение, требующее большого количества вычислений на стороне клиента, может извлечь выгоду из веб-воркеров.
Скажем, например, ваше приложение хочет создать отчет об использовании и сохраняет все данные на клиенте из соображений конфиденциальности.
Чтобы сгенерировать этот отчет, ваше веб-приложение должно получить данные, выполнить расчеты, упорядочить результаты и представить их пользователю.
Если бы вы попытались сделать это в основном потоке, пользователь совершенно не смог бы использовать приложение, пока приложение обрабатывает данные. Вместо этого вы можете переместить часть или весь этот код в веб-воркер. Это позволяет пользователю продолжать использовать приложение во время выполнения расчетов.
Как использовать веб-воркеров в JavaScript
API веб-работника определяет, как использовать веб-воркеров. Использование этого API предполагает создание объекта Worker с помощью конструктора Worker следующим образом:
пусть newWorker = Worker('рабочий.js');
Рабочий конструктор принимает имя файла JavaScript в качестве своего параметра и запускает файл в новом потоке. Он возвращает объект Worker, позволяющий основному потоку взаимодействовать с рабочим потоком.
Рабочие взаимодействуют с основным потоком, отправляя сообщения туда и обратно. Вы используете postMessage функция для отправки событий между рабочим и основным потоком. Использовать сообщение прослушиватель событий для прослушивания сообщений от другой стороны.
Вот пример кода. Во-первых, основной поток может выглядеть так:
позволять рабочий = новый Рабочий('worker.js')
рабочий.postMessage('Привет!')
рабочий.onmessage = функция(е) {
console.log('Рабочий поток говорит', э.данные)
}
Этот основной поток создает рабочий объект из worker.js, а затем отправляет ему сообщение с worker.postMessage. Затем он определяет прослушиватель событий, похожий по концепции на Слушатель событий DOM. Событие будет срабатывать каждый раз, когда рабочий процесс отправляет сообщение обратно в основной поток, а обработчик записывает сообщение рабочего процесса на консоль.
Код внутри воркера (worker.js) имеет одно задание:
сообщение = функция(е) {
позволять сообщение = электронные данные;
console.log('Основной поток сказал', сообщение);
сообщение('Привет!')
}
Он прослушивает любые сообщения, отправленные из основного потока, записывает сообщение в консоль и отправляет ответное сообщение обратно в основной поток.
Все сообщения в этом примере были строками, но это не обязательно: вы можете отправлять в виде сообщения практически любой тип данных.
Работников, которых вы видели до сих пор, называют преданными работниками. Вы можете получить к ним доступ только из файла, в котором вы их создали (они посвящены ему). Общие рабочие процессы противоположны: они могут получать сообщения и отправлять сообщения нескольким файлам. Общие рабочие роли концептуально такие же, как выделенные рабочие, но вы должны использовать их немного по-другому.
Давайте посмотрим на пример. Вместо использования конструктора Worker каждый файл, который хочет использовать общий рабочий процесс, должен создать рабочий объект, используя Общий рабочий():
позволять общий рабочий = новый SharedWorker('worker.js')
Однако на этом различия не заканчиваются. Чтобы файл мог отправить или получить сообщение от общего работника, он должен сделать это, обратившись к порт объект, вместо того, чтобы делать это напрямую. Вот как это выглядит:
sharedWorker.port.postMessage('Всем привет!')
sharedWorker.port.onMessage = функция(е) {
console.log('Общий рабочий отправлен', е.данные);
}
Вы также должны использовать объект порта внутри рабочего:
при подключении = функция(е) {
константа порт = электронные порты[0];
порт.onmessage = функция(е) {
console.log('Сообщение получено', э.данные)
порт.postMessage('Привет!');
}
}
при подключении прослушиватель срабатывает каждый раз, когда происходит подключение к порту (когда сообщение прослушиватель событий настроен в основном потоке).
Когда это происходит, код получает порт, к которому только что было подключено, из события подключения и сохраняет его в переменной. Далее код регистрирует сообщение прослушиватель объекта порта. Затем код записывает сообщение в консоль и использует порт для отправки сообщения обратно в основной поток.
Веб-воркеры улучшают взаимодействие с пользователем
Веб-воркеры — это потоки JavaScript, которые позволяют выполнять сложные и длительные фрагменты кода в фоновом режиме. Этот код позволит избежать блокировки пользовательского интерфейса. Использование веб-воркеров значительно упрощает написание такого кода и улучшает работу пользователя с приложением. Вы можете создавать веб-воркеры и взаимодействовать с ними с помощью API веб-воркеров.