Chapter 6.6โ˜• 15 min read

Resolvers โ€” Pre-fetch Data Before Route

Fetch data BEFORE the route component loads. The component gets data immediately, no spinner needed.

01What is a Resolver

A resolver fetches data BEFORE the route component loads. It ensures the component has the data it needs the moment it renders.

"Resolver = advance booking โ€” biryani pehle ban ke ready ho, tum aao toh khao."

Without a resolver:

  1. Component loads (shows empty/loading state)
  2. ngOnInit makes API call
  3. API responds (1-3 seconds later)
  4. Component renders actual content

With a resolver:

  1. API call completes (1-3 seconds)
  2. Component loads WITH data
  3. No loading state needed
02Creating a Functional Resolver

In modern Angular, resolvers are plain FUNCTIONS, not classes.

// biryani.resolver.ts
import { inject } from '@angular/core';
import { ResolveFn } from '@angular/router';
import { BiryaniService } from './biryani.service';

export const biryaniResolver: ResolveFn = (route) => {
  const service = inject(BiryaniService);
  const id = route.paramMap.get('id')!;
  return service.getBiryaniById(+id);
};

"Resolver = waiter โ€” kitchen se data laake table pe rakhta hai, tum aao toh ready."

The resolver receives the ActivatedRouteSnapshot (which has the params) and returns data synchronously or asynchronously (Observable/Promise). Angular WAITS for the data to arrive before activating the route.

03Using Resolver in Route

The resolver is connected to the route via the resolve property.

// Route config
{ path: 'menu/:id', component: BiryaniDetailComponent,
  resolve: { biryani: biryaniResolver }
}

Reading resolved data in the component:

// NEW WAY โ€” signal
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({...})
export class BiryaniDetailComponent {
  private route = inject(ActivatedRoute);
  biryani = this.route.data.signal()['biryani'];
}

// OLD WAY โ€” subscribe
this.route.data.subscribe(data => {
  this.biryani = data['biryani'];
});

"Route pe resolve laga do, component mein seedha use karo."

The resolved data is stored in route.data under the key you specified in the resolve config โ€” in this case, data['biryani'].

04Resolver with Error Handling

What happens if the API fails inside a resolver? The resolver should handle errors gracefully.

// Error handling in resolver
import { catchError, of } from 'rxjs';
import { inject } from '@angular/core';
import { ResolveFn, Router } from '@angular/router';

export const biryaniResolver: ResolveFn = (route) => {
  const service = inject(BiryaniService);
  const router = inject(Router);
  const id = route.paramMap.get('id')!;

  return service.getBiryaniById(+id).pipe(
    catchError(error => {
      console.error('Failed to load biryani:', error);

      // Option 1: Return null silently (component handles missing data)
      return of(null);

      // Option 2: Redirect to error page (navigation never completes)
      // return router.createUrlTree(['/not-found']);
    })
  );
};

"API fail ho toh app crash nahi hona chahiye โ€” graceful handling."

The Router can also be injected in the resolver to redirect on error. If you return a UrlTree, the current navigation is cancelled and replaced with the redirect.

05Resolver vs Component Fetch โ€” When to Use What

Not every route needs a resolver. Use the right approach based on requirements:

Use a resolver when:

  • Data is MANDATORY for the page to make sense (/menu/:id needs biryani data)
  • You want to avoid loading spinners for critical data
  • The data doesn't change frequently during the session

Use component fetch when:

  • Data is OPTIONAL or supplementary (sidebar stats, recommendations)
  • Data changes frequently (real-time updates, live feeds)
  • You want progressive loading โ€” layout first, data later
  • The data load could be slow and you prefer showing a loading state

"Resolver = mandatory data, Component fetch = optional data."

Key Takeaways

  • โœ… Resolvers pre-fetch data BEFORE the route component loads โ€” no spinner needed
  • โœ… Functional resolvers use ResolveFn โ€” just a function, no class needed
  • โœ… Resolved data is stored in route.data['key'] and read via signal() or subscribe()
  • โœ… Always handle errors in resolvers โ€” return null or redirect on failure
  • โœ… Use resolvers for mandatory data, component fetch for optional/frequently-changing data
Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase