Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Web Workers в JavaScript: типы и различия
Воркеры — это потоки, работающие в фоне параллельно с основным потоком (main thread). Это позволяет не блокировать UI при выполнении тяжёлых операций. Существует несколько типов воркеров, каждый с собственными особенностями.
1. Web Worker (Dedicated Worker)
Обычный воркер, работающий с одним script'ом в отдельном потоке:
// main.js (основной поток)
const worker = new Worker('worker.js');
// Отправляем сообщение в worker
worker.postMessage({ task: 'heavy-computation', data: [1, 2, 3] });
// Получаем результат
worker.onmessage = (event) => {
console.log('Result from worker:', event.data);
// Обновляем UI
};
// worker.js (отдельный поток)
self.onmessage = (event) => {
const { task, data } = event.data;
if (task === 'heavy-computation') {
// Тяжёлые вычисления (не блокирует UI)
const result = data.reduce((a, b) => a + b, 0);
// Отправляем результат назад
self.postMessage({ result });
}
};
Характеристики Web Worker:
- Dedicated — каждый worker работает только с одним главным потоком
- Отдельный контекст — нет доступа к DOM, window
- Постоянно живущий — существует до явного terminate()
- Высокие затраты — инициализация требует памяти и времени
- Медленное сообщение — данные копируются (deep copy), не по ссылке
2. Shared Worker
Воркер, который может использоваться несколькими вкладками/окнами одного источника:
// main.js (вкладка 1 и вкладка 2 одновременно)
const sharedWorker = new SharedWorker('shared-worker.js');
// Используем port для коммуникации
sharedWorker.port.start();
sharedWorker.port.postMessage({ action: 'increment' });
sharedWorker.port.onmessage = (event) => {
console.log('Counter:', event.data);
};
// shared-worker.js
let counter = 0;
self.onconnect = (event) => {
const port = event.ports[0];
port.start();
port.onmessage = (event) => {
if (event.data.action === 'increment') {
counter++;
// Отправляем всем подключённым вкладкам
port.postMessage(counter);
}
};
};
Характеристики Shared Worker:
- Shared — несколько контекстов могут использовать один worker
- Требует port — коммуникация через port
- Синхронизация — все вкладки видят одно состояние
- Сложнее в отладке — работает с несколькими потребителями
- Меньше поддержки — не поддерживается в Safari и IE
3. Service Worker
Специальный воркер для кэширования, offline поддержки и push-уведомлений:
// main.js
navigator.serviceWorker.register('sw.js')
.then(reg => console.log('Service Worker registered'))
.catch(err => console.error('Registration failed'));
// Отправляем сообщение в Service Worker
navigator.serviceWorker.controller.postMessage({ action: 'sync' });
// sw.js (Service Worker)
self.addEventListener('install', event => {
// Кэширование ассетов при установке
event.waitUntil(
caches.open('v1').then(cache => {
return cache.addAll(['/index.html', '/style.css']);
})
);
});
self.addEventListener('fetch', event => {
// Перехват всех fetch'ей
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
self.addEventListener('push', event => {
// Push-уведомления
const data = event.data.json();
self.registration.showNotification(data.title);
});
Характеристики Service Worker:
- Специальный назначение — кэширование, offline, push
- Жизненный цикл — install, activate, fetch
- Перехват сети — может работать как proxy
- Долгоживущий — сохраняется между сеансами
- Требует HTTPS (кроме localhost)
4. Web Worker vs Shared Worker vs Service Worker
| Параметр | Web Worker | Shared Worker | Service Worker |
|---|---|---|---|
| Назначение | Вычисления | Общие данные | Кэширование, offline |
| Область | Одна вкладка | Все вкладки домена | Весь домен |
| Коммуникация | postMessage | port.postMessage | navigator.serviceWorker |
| Доступ к DOM | НЕТ | НЕТ | НЕТ |
| Доступ к Storage | IndexedDB | IndexedDB | IndexedDB, Cache API |
| Требует HTTPS | НЕТ | НЕТ | ДА (кроме localhost) |
| Поддержка | Хорошая | Плохая | Хорошая |
| Сложность | Низкая | Средняя | Высокая |
Практические примеры
Пример 1: Тяжёлые вычисления (Web Worker)
// main.js
const computePrimes = (max) => {
const worker = new Worker('primes.js');
return new Promise((resolve) => {
worker.postMessage(max);
worker.onmessage = (e) => {
resolve(e.data);
worker.terminate(); // Очищаем память
};
});
};
await computePrimes(100000);
// primes.js
self.onmessage = (event) => {
const max = event.data;
const primes = [];
for (let i = 2; i <= max; i++) {
let isPrime = true;
for (let j = 2; j < i; j++) {
if (i % j === 0) {
isPrime = false;
break;
}
}
if (isPrime) primes.push(i);
}
self.postMessage(primes);
};
Пример 2: Service Worker для offline
// sw.js
const CACHE = 'my-cache-v1';
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request)
.then(response => {
if (!response || response.status !== 200) {
return response;
}
// Кэшируем успешные запросы
const clone = response.clone();
caches.open(CACHE).then(cache => {
cache.put(event.request, clone);
});
return response;
})
.catch(() => {
// Offline: вернём из кэша
return caches.match(event.request);
})
);
});
Пример 3: Shared Worker для синхронизации
// shared-counter.js
let counter = 0;
const ports = [];
self.onconnect = (event) => {
const port = event.ports[0];
ports.push(port);
port.start();
port.onmessage = (e) => {
if (e.data.action === 'increment') {
counter++;
// Уведомляем все вкладки
ports.forEach(p => p.postMessage({ counter }));
}
};
};
Когда использовать каждый
Web Worker:
- Факториалы, простые числа, обработка больших массивов
- Сортировка, поиск, шифрование
- Обработка видео/аудио
- Вычисление graphics
Shared Worker:
- Синхронизация состояния между вкладками
- Multiplayer games (общая логика)
- Real-time notifications
Service Worker:
- Offline support
- Кэширование стратегии
- Background sync
- Push-уведомления
Проблемы и решения
1. Service Worker не обновляется
// Явное обновление
navigator.serviceWorker.ready.then(reg => {
reg.update();
});
2. Проблема с данными в Worker
// ❌ Медленно: deep copy
worker.postMessage({ largeArray: [...Array(1000000)] });
// ✅ Быстро: transferable objects
const buffer = new ArrayBuffer(data);
worker.postMessage({ buffer }, [buffer]); // Трансферируем, не копируем
Вывод
- Web Worker — для CPU-интенсивных операций
- Shared Worker — для синхронизации между вкладками (редко используется)
- Service Worker — для кэширования и offline
Выбор зависит от задачи, но в 2026 году Service Worker используется чаще всего для PWA приложений.