Наводим порядок в загрузке данных Angular с помощью резолверов
Всем привет! Сегодня хочу разобрать кейс, с которым сталкивается почти каждый Angular-разработчик на существующем проекте.
Часто в компонентах можно встретить такой код:
Все загрузки данных у нас происходят в ngOnInit, и вот в чем беда: данные загружаются с разной скоростью. В итоге пользователи видят, как на месте блоков с данными появляются скелетоны или лоадеры, и потом контент показывается частями. Это может привести к смещению макета. Даже если интерфейс вроде бы нормальный, появление всплывающего контента все равно портит общее впечатление. Как это исправить? Можно использовать резолверы в Angular. Это такой сервис, который загружает данные перед тем, как активировать маршрут. Это еще и позволяет кэшировать данные, чтобы при повторном переходе они не загружались заново. Мы также можем использовать события маршрутизатора, чтобы сделать общий индикатор загрузки.Давайте начнем с написания резолвера.
Сначала определим DTO, который опишет структуру наших данных:
Теперь сам резолвер:
Я использовал forkJoin из RxJS, который ожидает завершения всех Observable и возвращает объект с результатами, ключи которого соответствуют ключам в переданном объекте.
Затем мы используем написанный нами резолвер в конфигурации маршрута:
Теперь наш компонент будет выглядеть так:
Мы забираем загруженные нашим резолвером данные из route.snapshot.data. Это безопасно и не требует отписки, так как резолвер отрабатывает один раз при навигации на маршрут.
Глобальный индикатор загрузки
Показывать лоадер мы можем через флаг isLoading в главном компоненте приложения, подписавшись на события роутера. Важно не забыть отписаться, чтобы избежать утечек памяти.
Кэширование и валидация
Резолвер - идеальное место для кэширования. Вот пример с использованием localStorage:
Для инвалидации кэша в нашем примере достаточно удалить ключ по которму мы храним кэш:
Еще один плюс загрузки данных в резолверах это то, что здесь удобно проводить валидацию данных, например, с помощью Zod:
Таким образом, используя резолвер, мы предзагружаем данные до активации маршрута, гарантируя, что весь необходимый контент будет готов к отображению. Это не только избавит наш UI от мигания, при подгрузке данных но и убирает CLS. Кроме того, мы получаем единую точку для загрузки, кэширования, валидации и трансформации данных.