Как выполнить тяжеловесный код на конскрипшн и сделать это максимально гладко для пользователя
Что проверяют
Понимаете ли вы, что JavaScript на странице выполняется в одном главном потоке вместе с рендерингом и обработкой ввода. Любая задача дольше 50 мс уже ощущается как подвисание. Следом спрашивают, как вы это измерите и как проверите результат.
Как отвечать
Сначала диагностика: вкладка Performance в DevTools, long tasks, метрика INP. Потом выбор по характеру работы:
- вынести из главного потока: чистые вычисления (парсинг большого JSON, фильтрация тысяч строк, обработка изображений) уходят в Web Worker. Общение через
postMessageсо структурным клонированием, а крупные буферы стоит передавать как transferable (ArrayBuffer), без копирования. Для удобства есть обёртка Comlink; - порезать на куски: если работа трогает DOM и в воркер не уходит, её делят на порции и между ними возвращают управление браузеру. Современный способ
scheduler.yield()там, где он поддерживается, запаснойsetTimeout(0); - отложить неважное:
requestIdleCallbackдля аналитики и прогрева кеша, динамическийimport()для тяжёлых модулей; - снизить приоритет обновлений в React:
useTransitionиuseDeferredValueоставляют ввод отзывчивым, пока тяжёлый список перерисовывается; - сократить объём: виртуализация длинных списков, мемоизация,
OffscreenCanvasдля графики в воркере, WebAssembly для числодробилок.
Для пользователя гладкость это ещё и обратная связь: мгновенная реакция на клик, индикатор прогресса, возможность отменить операцию через AbortController или worker.terminate().
Где спотыкаются
Советуют requestAnimationFrame для тяжёлых вычислений. Колбэк выполняется в том же главном потоке перед отрисовкой кадра и только удлиняет этот кадр.
Думают, что async/await или Promise разгружают поток. Асинхронность не делает код параллельным, синхронный цикл внутри async функции блокирует страницу так же.
Переносят задачу в воркер, а потом гоняют туда и обратно мегабайты данных копированием. Стоимость клонирования съедает выигрыш, поэтому здесь нужна передача владения буфером или обработка данных прямо в воркере.