Пара слов о веб‑воркерах

О сервис‑воркерах слышали все. А вот когда разговор заходит о веб‑воркерах, часто я встречаю вопрос «А что это?». В этом посте расскажу подробнее, что это такое и когда эту технологию стоит использовать.

Что за зверь

Веб‑воркер — штука, которая умеет выполняться в браузере параллельно с основным скриптом. А значит — выполняться, не блокируя отрисовку страницы. Проще говоря, если запустить что‑то тяжёлое в основном скрипте, то страница будет тормозить, а если в веб‑воркере — то не будет.

Что нужно знать перед началом

  • Джаваскрипт всё‑таки однопоточный, поэтому если мы хотим запустить какую‑то задачу параллельно, то она должна лежать в отдельном файле.
  • Веб‑воркер не имеет доступа ни к ДОМ‑дереву, ни к объекту window. Напрямую к локальному хранилищу обратиться внутри него тоже нельзя. Всё потому, что работа с ДОМ‑деревом и локальным хранилищем — последовательная, а веб‑воркер работает параллельно.
  • Общаться с веб‑воркером придётся через сообщения, которые нужно пересылать между ним и основным скриптом. Но стоит учитывать, что передача объектов по ссылке внутрь воркера не сработает, объекты будут скопированы перед отправкой.

АПИ

У веб‑воркеров простое АПИ. Чтобы проверить, поддерживается ли технология браузером:

if (window.Worker) {...}

Чтобы создать воркер:

const worker = new Worker('./path/to/file.js')
// путь должен быть прописан относительно .html, 
// в котором подключается основной скрипт

Чтобы отправить сообщение из основного скрипта в воркер:

worker.postMessage({key: 'value'})

Чтобы подписаться на сообщение внутри воркера:

self.onmessage = e => 
  console.log(e)
// self — глобальный объект внутри воркера,
// как window в основном скрипте

Чтобы отправить сообщение из воркера в основной скрипт:

self.postMessage({key: 'value'})

И чтобы подписаться на сообщение от воркера в основном скрипте:

worker.onmessage = e =>
  console.log(e)

Пример

Я написал небольшой пример, где запустил сложные вычисления вначале в основном скрипте, а затем в веб‑воркере. После этого сравнил, как ведёт себя анимация, с помощью отладчика в Хроме.

Вначале попробовал сделать анимацию без ЦСС‑трансформаций, чтобы результат был нагляднее. Получилось так.

Без применения веб‑воркера анимация стопорится, и ФПС падает до 0. Так происходит потому, что процессор занят сложной задачей. На скриншоте видно, сколько места занял response — это вычисления:

Иллюстрация распределения процессорного времени

Веб‑воркер выполняется параллельно, поэтому анимация в среднем держится на уровне 60 ФПС. На скриншоте видно, что вычисления теперь выполняются отдельно:

Иллюстрация влияния веб-воркера на ФПС

Результат для анимации без ЦСС‑трансформаций видно и невооружённым глазом. Попробуйте покликать на разные кнопки сами.

ЦСС‑трансформации спасают положение, страница становится отзывчивее, а анимация глаже. Но даже с ними при чуть больших нагрузках ФПС падает до 45–50. С веб‑воркером ФПС стабильно держится на 60.

Зачем это

Выносить сложные вещи в отдельный скрипт кажется чем‑то надуманным, пока не столкнёшься с обработкой потоковых данных, больших текстов или чисел в браузере. На одном из проектов нашей команде потребуется анализ текста на клиенте, поэтому мы думаем в сторону веб‑воркеров.

Кто уже использует

Покедекс использует веб‑воркер для обзора изменений в shadow DOM. Из‑за этого приложение плавно скроллится и работает без подмерзаний даже на старых телефонах.

И на сладкое

Веб‑воркеры поддерживаются всеми браузерами, кроме Оперы Мини. Они работают даже в 11‑м ИЕ:

Поддержка браузерами

Поэтому пользуйтесь, классная же технология :–)

Доп. материалы

← Ссылки №11 «Мозг и тело» Сайен Бейлок →