Веб-воркеры

Узнайте, как запускать код JavaScript в фоновом режиме с помощью Web Workers

Вступление

JavaScript является однопоточным. Ничто не может работать параллельно одновременно.

Это здорово, потому что нам не нужно беспокоиться о целом ряде проблем, которые могут возникнуть при параллельном программировании.

С этим ограничением код JavaScript вынужден быть эффективным с самого начала, иначе у пользователя будет плохой опыт. Дорогостоящие операции должны быть асинхронными, чтобы избежать блокировки потока.

По мере роста потребностей приложений JavaScript это начало становиться проблемой в некоторых сценариях.

Веб-воркеры предоставляют возможность параллельного выполнения внутри браузера.

У них довольно много ограничений:

  • нет доступа кДОМ: объект Window и объект Document
  • они могут взаимодействовать с основной программой JavaScript, используя обмен сообщениями
  • они должны быть загружены из одного источника (домен, порт и протокол)
  • они не работают, если вы обслуживаете страницу с использованием файлового протокола (file://)

Глобальная область видимости веб-воркера, а не Window, который находится в основном потоке, являетсяWorkerGlobalScopeобъект.

Поддержка браузера для веб-воркеров

Довольно хорошо!

Browser support for web workers

Вы можете проверить поддержку веб-воркеров, используя

if (typeof Worker !== 'undefined') {
}

Создать веб-воркера

Вы создаете Web Worker, инициализируя объект Worker, загружая файл JavaScript из того же источника:

const worker = new Worker('worker.js')

Общение с веб-воркером

Есть два основных способа общения с веб-воркером:

Использование postMessage в объекте Web Worker

Вы можете отправлять сообщения, используяpostMessageнаWorkerобъект.

Важно: сообщение передается, а не передается.

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.js

onmessage = event => {
  console.log(event.data)
}

onerror = event => { console.error(event.message) }

Отправка сообщений

Рабочий может отправлять сообщения функции, которая его создала. используя свой глобальныйpostMessage()функция:

worker.js

onmessage = event => {
  console.log(event.data)
  postMessage('hey')
}

onerror = event => { console.error(event.message) }

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.onmessage = event => { console.log(event.data) }

Несколько прослушивателей событий

Если вы хотите настроить несколько слушателей дляmessageсобытие вместо использованияonmessageсоздать прослушиватель событий (применяется кerrorсобытие):

worker.js

addEventListener('message', event => {
  console.log(event.data)
  postMessage('hey')
}, false)

addEventListener(‘message’, event => { console.log(I'm curious and I'm listening too) }, false)

addEventListener(‘error’, event => { console.log(event.message) }, false)

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')

worker.addEventListener(‘message’, event => { console.log(event.data) }, false)

Использование API обмена сообщениями канала

Вместо использования встроенного API postMessage, предлагаемого веб-воркерами, мы можем использовать более универсальныйChannel Messaging APIобщаться с ними.

main.js

const worker = new Worker('worker.js')
const messageChannel = new MessageChannel()
messageChannel.port1.addEventListener('message', event => {
  console.log(event.data)
})
worker.postMessage(data, [messageChannel.port2])

worker.js

addEventListener('message', event => {
  console.log(event.data)
})

Веб-воркер может отправлять сообщения обратно, отправив сообщение наmessageChannel.port2, так:

addEventListener('message', event => {
  event.ports[0].postMessage(data)
})

Жизненный цикл веб-воркера

Веб-воркеры запускаются, и если они не остаются в режиме прослушивания сообщений черезworker.onmessageили добавив слушателя событий, они будут закрыты, как только их код будет выполнен до конца.

Веб-воркер можно остановить, используя егоterminate()из основного потока, а внутри самого рабочего с помощью глобального методаclose():

main.js

const worker = new Worker('worker.js')
worker.postMessage('hello')
worker.terminate()

worker.js

worker.onmessage = event => {
  console.log(event.data)
  close()
}

worker.onerror = event => { console.error(event.message) }

Загрузка библиотек в Web Worker

Веб-воркеры могут использоватьimportScripts()глобальная функция, определенная в их глобальной области видимости:

importScripts('../utils/file.js', './something.js')

API, доступные в Web Workers

Как было сказано ранее, DOM недоступен для Web Worker, поэтому вы не можете взаимодействовать сwindowиdocumentобъекты. Такжеparentнедоступен.

Однако вы можете использовать многие другие API, в том числе:

Скачать мою бесплатнуюРуководство для начинающих по JavaScript


Больше руководств по браузеру: