03.02.2025, Ссылка на статью
Таски. Они везде, мы постоянно пишем код, который можно назвать тасками. Разделить их тоже можем — на макротаски и микротаски, хоть это и не всегда верное утверждение1. Для простоты назовем весь синхронный код, где бы он не вызвался - макротасками. Использование макротасок заставляет и браузер выполнять определенные процессы внутри них, например reflow2 и repaint3. Такое поведение может стать бутылочным горлышком в некоторых сценариях, например расчет размеров элементов, особенно если их много. Решением может быть разделение макротаски на несколько макротасок.
Как много вы можете придумать способов разбиения долгих макротасок? Я смог придумать только 3 — setTimeout
, requestAnimationFrame
, requestIdleCallback
, и оказалось, что не все способы хороши. А вот Алекс МакАртур, автор статьи “Способы разбиения длинных задач в JavaScript” рассказал больше способов:
setTimeout
;async/await & setTimeout
;scheduler.postTask()
;scheduler.yield()
;requestAnimationFrame()
;MessageChannel()
;- и использование
Web Workers
.
А вот использование requestIdleCallback
автор исключает, т.к. он не гарантирует исполнение кода.
[! tip] Не стоит забывать про
requestIdleCallback
Данная функция является очень важной для оптимизации приложений, например тех же часто вызывающихся reflow. Функция попросит браузер найти “окошко” для его исполнения, хоть оно может и найтись сильно позже.
Как отмечает автор, лучшим вариантом является scheduler.yield()
, но пока Scheduler есть только в Хроме мы можем использовать подход с async/await & setTimeout
:
await new Promise((resolve) => setTimeout(resolve, 0));
Footnotes
-
В спецификации ECMAScript нет прямого упоминания “макрозадач” и “микрозадач”, данные термины удобны в рамках описания работы Event Loop. ↩
-
Процесс, при котором браузер пересчитывает позиции и размеры элементов. Может вызвано обращением к
clientHeight
,clientWidth
и т.д., подробнее описано в What forces layout / reflow. ↩ -
Процесс, при котором браузер перерисовывает изменения, затронутые reflow. ↩