> Как использовать несколько потоков в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: intelsy

Стек: JavaScript

> Пример ответа

Короткий ответ

JavaScript - однопоточный язык с event loop, но многопоточность доступна через Web Workers (браузеры) и Worker Threads (Node.js). Они создают изолированные потоки с собственным контекстом, общающиеся через сообщения (postMessage). Для CPU-интенсивных задач используют также SharedArrayBuffer для разделяемой памяти и Atomics для синхронизации. Основной поток не блокируется, но workers не имеют доступа к DOM или глобальным объектам.

Подробное объяснение

В JavaScript исторически нет настоящей многопоточности из-за однопоточной модели event loop. Однако для параллельного выполнения существуют:

  • Web Workers (браузеры): создаются через new Worker('script.js'). Каждый worker работает в отдельном потоке, не имеет доступа к DOM, window, document. Общение - через postMessage и событие message. Workers могут быть вложенными и создавать subworkers.

  • Worker Threads (Node.js): модуль worker_threads. Аналогичны Web Workers, но имеют доступ к Node.js API (кроме некоторых). Используются для CPU-нагрузки, например, обработки изображений или шифрования.

  • SharedArrayBuffer: позволяет нескольким потокам читать/писать общую память. Требует заголовков безопасности (Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy). Используется с Atomics для атомарных операций и синхронизации.

  • Service Workers: не для многопоточности в классическом смысле, но работают в фоновом потоке для перехвата запросов и кэширования.

  • OffscreenCanvas: позволяет рендерить графику в worker.

Ограничения: workers не могут напрямую изменять DOM, требуют сериализации данных (структурное клонирование или transferable objects), имеют накладные расходы на создание.

На практике

Используйте workers для:

  • Тяжелых вычислений (криптография, парсинг данных, обработка медиа)
  • Фоновой загрузки и обработки файлов
  • Реалтайм-аналитики (например, обработка аудиопотока)
  • Параллельных запросов к API (хотя это можно сделать через Promise.all)

Не используйте workers для:

  • Простых операций (накладные расходы выше выгоды)
  • Частого обмена большими данными (лучше transferable objects)
  • Работы с DOM (используйте основной поток)

На практике часто создают пул workers для балансировки нагрузки. В Node.js worker_threads удобны для изоляции тяжелых модулей, чтобы не блокировать основной поток сервера.

Пример кода

JAVASCRIPT
// main.js (браузер)
const worker = new Worker('worker.js');
worker.postMessage({ type: 'compute', data: [1, 2, 3, 4, 5] });
worker.onmessage = (event) => {
console.log('Результат:', event.data);
};
// worker.js
self.onmessage = (event) => {
const { data } = event.data;
const result = data.reduce((acc, val) => acc + val, 0);
self.postMessage(result);
};
JAVASCRIPT
// Node.js с worker_threads
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js', { workerData: { numbers: [1, 2, 3] } });
worker.on('message', (result) => console.log('Результат:', result));
worker.on('error', (err) => console.error(err));

Как отвечать на собеседовании

Начните с признания однопоточности JS, затем перечислите механизмы многопоточности. Упомяните различия между браузером и Node.js. Приведите пример, когда workers оправданы. Покажите понимание ограничений (DOM, сериализация). Если спросят про SharedArrayBuffer, объясните его назначение и требования безопасности. Избегайте путаницы с асинхронностью (async/await не делают код многопоточным).

Что проверяет интервьюер

  • Понимание event loop и однопоточной модели
  • Знание конкретных API (Web Workers, Worker Threads)
  • Умение выбирать правильный инструмент под задачу
  • Понимание trade-off (накладные расходы, изоляция, безопасность)
  • Знание продвинутых тем (SharedArrayBuffer, Atomics, transferable objects)

Типичные ошибки

  • Путать асинхронность с многопоточностью (setTimeout не создает поток)
  • Пытаться использовать workers для DOM-операций
  • Забывать про сериализацию данных (передавать функции или циклические ссылки)
  • Создавать worker на каждую мелкую задачу (лучше пул)
  • Игнорировать заголовки безопасности для SharedArrayBuffer
  • Думать, что workers в Node.js имеют полный доступ ко всем модулям (некоторые ограничены)

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью