Skip to main content

Web Workers у JavaScript

Web Worker це окремий потік виконання JavaScript-коду, який працює паралельно з головним потоком (UI thread). Він не блокує інтерфейс: важкі обчислення виконуються у фоні, а результат повертається в головний потік повідомленням.

Теорія

TL;DR

  • JavaScript у браузері однопотоковий: рендеринг, обробка подій і ваш код живуть в одному потоці.
  • Важкий синхронний цикл займає Event Loop, і сторінка «замерзає».
  • Web Worker виносить обчислення в окремий потік, тому UI лишається чуйним.
  • Спілкування між потоками йде тільки через повідомлення: postMessage та onmessage, дані серіалізуються алгоритмом structured clone.
  • Воркер не має доступу до document, window, alert(), localStorage, але має fetch, XMLHttpRequest, WebSocket, setTimeout, indexedDB, crypto.
  • Типів три: Dedicated Worker, Shared Worker, Service Worker.

Швидкий приклад

javascript
// main.js const worker = new Worker('worker.js'); worker.postMessage(1e9); // надсилаємо задачу worker.onmessage = (event) => { console.log('Result:', event.data); };
javascript
// worker.js onmessage = (event) => { let sum = 0; for (let i = 0; i < event.data; i++) sum += i; postMessage(sum); // повертаємо результат назад };

Тепер важкий розрахунок виконується у фоні, а UI лишається чуйним.

Проблема однопотокового JavaScript

JavaScript у браузері однопотоковий, тобто в одному потоці відбувається все одразу:

  • рендеринг сторінки
  • обробка подій
  • виконання вашого коду

Якщо в цьому потоці запустити важкий цикл:

javascript
for (let i = 0; i < 1e9; i++) {} console.log('Done!');

сторінка «замерзне»: інтерфейс перестане реагувати, доки цикл не закінчиться, бо Event Loop зайнятий.

Як це працює під капотом

  1. Головний потік створює воркера через new Worker('script.js').
  2. Браузер запускає окремий потік JS.
  3. Спілкування між потоками йде через повідомлення (message passing).
  4. Передача асинхронна, дані серіалізуються (structured clone).
  5. Воркер не має доступу до DOM, window і document.

Обмін даними (message passing)

Комунікація йде через події postMessage і onmessage:

javascript
// main.js worker.postMessage({ action: 'sum', a: 5, b: 7 }); // worker.js onmessage = (e) => { if (e.data.action === 'sum') { postMessage(e.data.a + e.data.b); } };

Передавати можна:

  • рядки, числа, об'єкти
  • ArrayBuffer, Blob, File, ImageBitmap
  • навіть Transferable об'єкти, щоб передавати без копіювання

Обмеження та доступне API

Web Worker ізольований:

  • немає доступу до document, window, alert(), localStorage
  • є доступ до fetch, XMLHttpRequest, WebSocket, setTimeout, indexedDB, crypto і подібного

Потокова обробка даних у воркері

Воркер може використовувати Streams і Fetch API:

javascript
onmessage = async (e) => { const response = await fetch(e.data.url); const text = await response.text(); postMessage(text.length); };

Так можна обробляти мережеві дані у фоні, взагалі не блокуючи UI.

Види Web Workers

ТипДе використовуєтьсяОсобливості
Dedicated WorkerОдин на одногоПрацює лише зі скриптом, який його створив
Shared WorkerКілька вкладок або скриптівОдин воркер для всіх сторінок (за origin + URL)
Service WorkerМіж браузером і мережеюКешує запити, працює навіть офлайн

Приклад Shared Worker

javascript
// shared-worker.js onconnect = (event) => { const port = event.ports[0]; port.onmessage = (e) => { port.postMessage(`Received: ${e.data}`); }; };

Кілька вкладок можуть під'єднуватися до одного Shared Worker, наприклад щоб обмінюватися даними між вкладками.

Service Worker як окремий тип

Service Worker це не просто потік, а «проксі» між браузером і мережею.

Він перехоплює HTTP-запити, кешує відповіді і дозволяє працювати офлайн. Приклади: PWA-застосунки, push-сповіщення, фонові синхронізації.

javascript
// service-worker.js self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then((cached) => { return cached || fetch(event.request); }) ); });

Це означає: якщо є закешована відповідь, віддати її, інакше завантажити з мережі.

Приклад «паралельних» обчислень

javascript
const workers = Array.from({ length: 4 }, () => new Worker('calc.js')); let completed = 0; let result = 0; workers.forEach((w, i) => { w.postMessage(i); w.onmessage = (e) => { result += e.data; if (++completed === 4) console.log('Done:', result); }; });

Так можна розподілити обчислення між кількома потоками, це «псевдопаралелізм».

Коли варто використовувати Web Workers

СценарійЧому корисно
Складні обчисленняпарсинг JSON, криптографія, машинне навчання
Обробка великих данихфільтрація та агрегація масивів, обробка CSV
Робота із зображеннямистиснення, фільтри, генерація мініатюр
Ігри та анімаціярозрахунки фізики без лагів інтерфейсу
WebSocket плюс аналіз данихпотокова обробка

Проста аналогія:

Уявіть, що браузер це кухня. Головний потік (основний JS) це кухар, який готує страву і обслуговує гостей. Web Worker це помічник на іншій кухні, який нарізає овочі. Кухар дає завдання, помічник виконує його у фоні і повертає результат. Ніхто нікому не заважає.

Підсумок:

КомпонентЩо робить
Web WorkerОкремий потік для виконання коду
Головна перевагаНе блокує UI
Обмін данимиЧерез postMessage / onmessage
ОбмеженняНемає доступу до DOM, window, document
ТипиDedicated, Shared, Service Worker
Основні застосуванняФонові обчислення, кеш, офлайн-режим, синхронізація

Типові помилки

  • Звертатися до document чи window усередині воркера. Їх там немає, потрібні дані треба передати повідомленням.
  • Чекати, що об'єкт передасться за посиланням. Дані копіюються через structured clone, тож великі масиви краще віддавати як Transferable (ArrayBuffer), інакше копіювання само по собі стане вузьким місцем.
  • Передавати у postMessage функції, DOM-вузли або класи з методами. Structured clone їх не підтримує і кине помилку.
  • Створювати новий воркер на кожен дрібний виклик. Запуск потоку коштує часу і пам'яті, воркери варто перевикористовувати або тримати їх пул.
  • Плутати Web Worker і Service Worker. Перший для обчислень, другий для перехоплення мережевих запитів і офлайн-режиму.
  • Забувати worker.terminate(). Воркер живе, доки його явно не зупинили або доки відкрита сторінка.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.