Как стать автором
Обновить

Ускорение в 30 раз — requestIdleCallback

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров9.7K

В данной статье я хотел бы привести пример практического кейса использования метода requestIdleCallback, который возник у меня на проекте. Кейс сам по себе небольшой, замеры времени отработки функции и отрисовки компонентов для использования производились с помощью React Profiler.

Хотелось бы сразу сказать, что статья может быть не чем-то новым, но может оказаться полезной в плане практического понимания того, где может пригодиться requestIdleCallback и как он может быть использован.

Коротко о проекте

Чтобы внести контекст, я упрощенно опишу проект в той части, с которой пришлось работать.

Это поисковик по различным материалам, выдача которых производится в таблице, количество столбцов и строк в которой можно регулировать. Соответственно, как и во всех поисковиках, присутствуют фильтры, которые организованы у нас в выезжающем по нажатию кнопки "Фильтры" сайдбару. В сайдбаре присутствуют несколько разворачивающихся списков с категориями фильтров (Основные, Параметр и т.п.) в которых лежат сами фильтры (тоже в свернутом виде, но с ними проблем нет). Фильтры могут быть разных типов: числовые, обычным списком чекбоксов для выбора, дерево фильтров (иерархия с зависимостями от родительского фильтра) и т.п.

Для наглядности скрин сайдбара с фильтрами

Теперь к делу

Недавно на проекте появилось немного свободного времени и на меня упала задача прошерстить код и выделить части проекта, которые необходимо отрефакторить и выписать все это в отдельную задачу тех. долга (и возможно что-то сразу пофиксить).

Я, недолго думая, пошел смотреть фильтры, так как знал, что там могут быть определенные проблемы. Это связано с тем, что когда-то давно, когда я только пришел на проект с ними уже была одна проблема. Она заключалась в том, что при большом количестве фильтров сайдбар после нажатия открывался через время, которое было чуть больше секунды, что очень долго.

Открытие сайдбара в самом начале
Открытие сайдбара в самом начале

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

Упрощенный код того, как все происходило
Упрощенный код того, как все происходило

Поправил я это достаточно просто на тот момент - поставил расчет с отрисовкой по условию, что если открыт, то считай. Открываться стало около 100мс, что очень хорошо.

После того, как поставили условие
После того, как поставили условие
Упрощенный код того, как все происходило
Упрощенный код того, как все происходило

Сделав так, я пожертвовал расчетами, которые происходили заранее и, как итог, замедлил открытие самих категорий, так как теперь расчеты происходили при их открытии, а значит появилась небольшая задержка перед тем, как список развернется. В тот момент, когда я это делал, фильтров было много, но должно было стать еще больше, так что решение было временным.

Время пришло...

И вот настал момент, когда появилось время на рефакторинг и когда фильтров начало становиться больше и в ближайшее время обещало увеличиться в достаточно большое количество (так как количество материалов с разными параметрами увеличивалось).

Один из самых многочисленных категорий фильтров - это Параметр (на скрине в спойлере в самом начале категория идет второй и по умолчанию свернута). При нажатии на нее расчет и открытие занимает около 100мс (да, на данный момент вроде как не так много, но небольшая задержка видна глазу, а если количество фильтров в категории увеличится, то и задержка вырастет).

Открытие категории
Открытие категории

Я начал думать, как можно решить данную проблему. И я придумал вариант, как можно это исправить - надо рассчитывать открытую категорию перед открытием сайдбара (как сейчас и происходит), а остальные категории рассчитывать не при нажатии на них, а заранее, после того, как сайдбар откроется.

Как это можно сделать?

Если чуть углубиться, то вся проблема возникает из-за того, что расчеты блокируют работу браузера и из-за этого все задержки. Значит надо отложить расчеты закрытых категорий, пока сайдбар не откроется.

По описанию такое действие как раз выполняет requestIdleCallback - данный метод откладывает выполнение задачи до тех пор, пока браузер не освободится от других задач, а значит это то, что нам нужно.

Каким образом я его применил?

Я вынес маппинг данных с расчетами и передачей в отрисовывающийся компонент в отдельную функцию, которая помещает данные в переменную, которая уже помещалась в код для отрисовки. И в зависимости от того, открыта ли категория, функция выполнялась либо сразу, либо помещалась в requestIdleCallback.

Упрощенный код с requestIdleCallback
Упрощенный код с requestIdleCallback

При таком подходе мы получили то, что теперь категория рассчитывалась заранее и стала открываться около 3мс.

Открытие категории после применения requestIdleCallback
Открытие категории после применения requestIdleCallback

Что в итоге?

В итоге мы получили то, что фильтры открываются на данный момент достаточно быстро и взаимодействие с ними при открытии различных категорий не затормаживается, а значит не вызывает визуального дискомфорта пользователей. Раньше категории разворачивались около 100мс, а сейчас около 3мс, а значит взаимодействие ускорилось где-то в 30 раз и как бы не казалось, что это маленькие цифры (хоть и порядок разницы большой), в будущем это может существенно сыграть в нашу пользу.

На данный момент requestIdleCallback все еще не поддерживается в Safari, но в нашем случае это не проблема, так как на проект вход идет с внутреннего контура и IOS там даже не пахло) В случае, если же все-таки есть пользователи с Safari я бы наверное попробовал провернуть что-то такое с использованием setTimeout.

Надеюсь эта статья будет кому-нибудь полезна для понимания использования и влияния requestIdleCallback и буду еще больше рад, если вы сможете привести дополнительные примеры использования данного метода.

Теги:
Хабы:
Всего голосов 7: ↑7 и ↓0+7
Комментарии14

Публикации

Истории

Работа

Ближайшие события

Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург