Guards и Interceptors

f

Что такое Guards и Interceptors: точное определение и зона ответственности

Guards (сторожевые охранники) — это сервисы, реализующие интерфейс CanActivate, CanActivateChild, CanDeactivate, Resolve или CanLoad. Interceptors (перехватчики) — это классы, реализующие HttpInterceptor. Guards работают на этапе маршрутизации до активации компонента. Interceptors работают на уровне HTTP-запросов и ответов, перехватывая каждый вызов HttpClient.

Ключевое различие: Guards управляют навигацией (логика доступа), Interceptors управляют потоком данных (логика преобразования). В реальном проекте Guards размещаются в массиве canActivate в конфигурации маршрута Route. Interceptors регистрируются через providers: [{ provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true }]. В Angular 2026 года рекомендуется использовать функциональные аналоги: CanActivateFn и HttpInterceptorFn — они легче и не требуют создания класса.

Технические детали Guards: схемы выполнения и параметры

Guards выполняются в порядке их объявления в массиве. Если хотя бы один Guard возвращает false или UrlTree, маршрутизация прерывается. При возврате UrlTree Angular выполняет редирект на указанный путь. Guards получают контекст через объект ActivatedRouteSnapshot и RouterStateSnapshot. Это даёт доступ к параметрам маршрута, query-параметрам, фрагментам и состоянию роутера.

В отличие от классических проверок в компоненте (например, через *ngIf), Guards гарантируют, что неавторизованный пользователь даже не увидит код компонента — он никогда не будет создан. Это снижает объём загружаемого JavaScript и ускоряет первое взаимодействие. Для сложных scopes (например, проверка прав на редактирование конкретной сущности) используйте Resolve для предзагрузки сущности, затем CanActivate для проверки прав.

Технические детали Interceptors: порядок выполнения и модификация потока

Interceptors образуют цепочку (chain). Каждый Interceptor получает HttpRequest и next: HttpHandler. Вызов next.handle(req) передаёт запрос следующему Interceptor'у или непосредственно в HttpBackend. Если Interceptor не вызывает next.handle(), запрос не будет отправлен — это можно использовать для отмены. Interceptors могут возвращать любой Observable<HttpEvent<any>>, включая модифицированные ответы или повторные попытки.

Отличие Interceptors от обычной обёртки HttpClient (например, через сервис) в том, что Interceptors применяются ко всем HTTP-вызовам без исключения, даже к тем, что сделаны через сторонние библиотеки, использующие HttpClient. Если нужно исключить некоторые запросы — проверяйте URL: if (req.url.includes('/api/public')) return next.handle(req);. В Angular 2026 появилась возможность регистрировать Interceptors по маске URL через параметр httpInterceptorWhitelist в provideHttpClient.

Отличие Guards и Interceptors от альтернатив: почему они лучше

Прямые альтернативы Guards в Angular — это проверки внутри компонента (в ngOnInit) или в сервисах, вызываемых компонентом. Разница: при использовании Guards компонент не создаётся вообще, что экономит память и ресурсы. При проверке внутри компонента Angular уже создаёт экземпляр, загружает шаблон, выполняет Data Binding — это излишне. Альтернатива Interceptors — отдельный сервис-обёртка над HttpClient, но такой подход не перехватывает запросы из библиотек, и его нужно внедрять в каждый компонент. Interceptors автоматически применяются ко всем инстансам HttpClient в приложении.

Важно: Interceptors не подходят для индикации загрузки на уровне компонента, если нужно показать прогресс только для конкретного вызова. Для этого используйте HttpContextToken (доступен с Angular 12+). Ключевое преимущество Interceptors — они единственный способ централизованно трансформировать ошибки HTTP (например, 401 → редирект на логин) без изменения каждого сервиса. Guards — единственный способ прервать навигацию до того, как компонент будет создан.

Практическая реализация Guards в 2026 году: функциональный подход

В современном Angular (версия 18+, 2026) рекомендуется использовать функциональные Guards — CanActivateFn, CanDeactivateFn и т.д. Они не требуют класса, DI выполняется через inject(). Пример функционального Guard для проверки аутентификации: export const authGuard: CanActivateFn = (route, state) => { const authService = inject(AuthService); const router = inject(Router); if (authService.isLoggedIn()) { return true; } return router.createUrlTree(['/login']); };

Если вам нужно передать данные в Guard (например, строку маршрута), используйте route.data или route.paramMap. Не создавайте Guards с состоянием (поля класса) — функциональные Guards иммутабельны и гарантируют предсказуемость. В одном проекте Angular 2026 может быть до 10–15 различных Guards: authGuard, adminGuard, ownerGuard, unsavedChangesGuard, pendingChangesGuard.

Практическая реализация Interceptors в 2026 году: функциональные Interceptor'ы

Начиная с Angular 15, появились функциональные Interceptor'ы — HttpInterceptorFn. Они регистрируются через provideHttpClient(withInterceptors([...])). Пример: export const loggingInterceptor: HttpInterceptorFn = (req, next) => { console.log(`[${req.method}] ${req.url}`); return next(req); };. Это компактнее классовой версии и не требует объявления в providers отдельного токена.

Ограничение функциональных Interceptor'ов: они не могут быть переданы через DI с multi: true (для них это не нужно). Порядок выполнения Interceptor'ов задаётся порядком в массиве withInterceptors. Если у вас есть классовые Interceptors (например, из библиотеки), их можно подключить через withInterceptorsFromDi(). В одном приложении можно комбинировать оба подхода, но приоритет отдавайте функциональным — они легче и быстрее.

Тестирование Guards и Interceptors: конкретные шаги

Для тестирования Guards используйте TestBed с моками сервисов. Проверьте, что Guard возвращает true, false или UrlTree в зависимости от состояния сервиса. Пример: const result = TestBed.runInInjectionContext(() => authGuard(mockRoute, mockState)); expect(result).toBe(true);. Для тестирования Interceptors — создайте экземпляр Interceptor, вызовите intercept с mock-запросом и mock-обработчиком, проверьте модифицированный запрос.

В крупных проектах (более 100 маршрутов) рекомендуется покрывать Guards модульными тестами, а Interceptors — интеграционными, запуская HttpClient через HttpTestingController. Это гарантирует, что токены ошибки обрабатываются централизованно. В 2026 году Angular CLI поддерживает генерацию тестов для Guards и Interceptors командой ng generate guard и ng generate interceptor.

Добавлено: 23.04.2026