Web Workers предоставляют возможность выполнения JavaScript-кода в фоновом потоке, отдельно от основного потока интерфейса. Это позволяет выполнять тяжёлые вычисления, не блокируя рендеринг страницы и обеспечивая плавность пользовательского опыта. Основная концепция заключается в том, что основной поток и воркеры работают в изоляции, а взаимодействие происходит через обмен сообщениями.
Создание воркера осуществляется с помощью конструктора
Worker:
const worker = new Worker('worker.js');
Внутри файла worker.js размещается код, который будет
выполняться в отдельном потоке. Для обмена данными используется метод
postMessage и обработчик события message:
worker.js:
self.onmess age = function(event) {
const result = event.data * 2;
self.postMessage(result);
};
main.js:
worker.postMessage(10);
worker.onmess age = function(event) {
console.log('Результат из воркера:', event.data);
};
Ключевой особенностью является то, что воркер не имеет доступа к DOM, что требует передачи данных через сообщения.
Существует несколько типов воркеров:
install и activate.В Preact, как и в React, интерфейс обновляется в основном потоке. Если необходимо выполнять тяжёлые вычисления (например, обработку больших массивов данных, фильтрацию или рендеринг сложных графиков), Web Workers позволяют вынести эти операции из UI-потока.
Пример использования Web Worker с Preact:
import { h, render, Component } from 'preact';
class HeavyComputation extends Component {
state = { result: null };
componentDidMount() {
this.worker = new Worker('./worker.js');
this.worker.postMessage([1, 2, 3, 4, 5]);
this.worker.onmess age = (event) => {
this.setState({ result: event.data });
};
}
componentWillUnmount() {
this.worker.terminate();
}
render({}, { result }) {
return <div>Результат: {result}</div>;
}
}
render(<HeavyComputation />, document.body);
В этом примере вычисления выполняются в отдельном потоке, а Preact отвечает только за рендеринг обновлённого состояния, что обеспечивает плавный интерфейс без зависаний.
Обмен данными осуществляется через структурное
клонирование. Это значит, что объекты и массивы копируются, а
не передаются по ссылке. Для больших массивов рекомендуется использовать
Transferable Objects, например
ArrayBuffer, чтобы избежать копирования данных:
const buffer = new ArrayBuffer(1024);
worker.postMessage(buffer, [buffer]);
После передачи буфера он становится недоступным в основном потоке, что снижает нагрузку на память и ускоряет передачу.
Пример реализации простого пула воркеров:
class WorkerPool {
constructor(size, script) {
this.workers = Array.from({ length: size }, () => new Worker(script));
this.queue = [];
}
runTask(data) {
return new Promise((resolve) => {
const worker = this.workers.shift();
worker.onmess age = (event) => {
resolve(event.data);
this.workers.push(worker);
if (this.queue.length) {
const next = this.queue.shift();
this.runTask(next.data).then(next.resolve);
}
};
if (worker) {
worker.postMessage(data);
} else {
this.queue.push({ data, resolve });
}
});
}
}
setTimeout, fetch).В Preact-приложениях часто используется Vite или Webpack для работы с воркерами через import-спецификаторы:
import Worker from './worker.js?worker';
const worker = new Worker();
Это позволяет автоматически обрабатывать скрипты воркеров, упрощает сборку и поддержку модулей.
Использование Web Workers в Preact обеспечивает высокую отзывчивость интерфейса при интенсивных вычислениях, позволяет создавать сложные приложения с параллельной обработкой данных и обеспечивает современный подход к многопоточности в браузере.