📝 Ответ
Тяжёлая и неделимую задачу можно вынести в:
Web Workers
Наиболее предпочтительный вариант. По факту, отдельный поток исполнения, общающийся с основным за счет сообщений (events).
У web worker нет доступа к DOM и нет возможности сделать сетевой запрос.
На backend (я не шучу)
Всегда можно договориться с бэкендерами, чтобы они реализовали логику на своей стороне. Они, в свою очередь, могут использовать весь доступный им арсенал:
- многопоточность ЯП (Например, Golang)
- брокеры сообщений (Kafka, Rabbit MQ)
Подходит, если задача действительно тяжёлая и независимая. Но не подойдет, если фронт вынужден гонять туда-сюда большие объёмы данных → задержка.
Для бэкенда на nodejs можно воспользоваться:
- worker_threads
- child_process / fork
⚖️ Компромиссы
- Web Workers → хорошо для CPU-bound, но сложно с отладкой, нет доступа к DOM (в браузере).
- Backend → снимает нагрузку, но добавляет latency и сетевую зависимость.
🔎 Встречные вопросы
- Чем Web Workers отличаются от Service Workers?
- Когда лучше использовать WebAssembly?
🚩 Красные флаги
- Можно оптимизировать через async/await (не решает CPU-bound).
- Просто вынесем в setTimeout (это не решение).
- JS многопоточный (фактологическая ошибка).
🛠 Практика
📚 Источники / ссылки
MDN Web DocsИспользование Web Workers - Интерфейсы веб API | MDN

Использование Web Workers - Интерфейсы веб API | MDN
Web Worker-ы предоставляют простое средство для запуска скриптов в фоновом потоке. Поток Worker'а может выполнять задачи без вмешательства в пользовательский интерфейс. К тому же, они могут осуществлять ввод/вывод, используя XMLHttpRequest (хотя атрибуты responseXML и channel всегда будут равны null). Существующий Worker может отсылать сообщения JavaScript коду-создателю через обработчик событий, указанный этим кодом (и наоборот). Эта статья даёт детальную инструкцию по использованию Web Workers.