All topics
Routingintermediate

Route Resolvers

Explain how resolvers pre-fetch data before route activation so a component never renders in a data-less state.

Without a resolver, a component typically fetches its own data inside ngOnInit, which means the component renders first (often showing a loading spinner or empty state) and then re-renders once the data arrives. A route resolver flips this order: it fetches the data as part of the navigation itself, before the route activates, so the component's ActivatedRoute data already contains what it needs the moment it's constructed.

It's like a restaurant that plates your entire meal in the kitchen before calling you to the table, rather than seating you first and bringing dishes out one at a time — you wait a bit longer before sitting down, but there's no empty-table moment once you do.

Key Concepts

1
Like guards, resolvers moved to a functional style (ResolveFn<T>) as the modern recommended approach, replacing the older class-based Resolve<T> interface. A resolver function returns the data directly, or a Promise/Observable of it, and the router waits for that to complete before finishing the navigation and activating the route's component.
ResolveFn<T>Resolve<T>PromiseObservable
2
Interviewers often ask about the trade-off resolvers introduce: navigation is blocked until the resolver's data arrives, which avoids a flash of empty/loading UI in the target component but means the user's click doesn't visually respond until the data-fetch finishes — this can feel sluggish for slow APIs unless paired with a route-level loading indicator (many apps show a top-of-page progress bar during this exact window, which not coincidentally is one of the standard Router events, NavigationStart/NavigationEnd, discussed in the Router Events topic).
RouterNavigationStartNavigationEnd
3
A balanced answer notes resolvers aren't always the right choice — for data that's not strictly required to render the initial view, or for data you want to stream in progressively, fetching inside the component (or using @defer) may give a better perceived-performance trade-off than blocking the whole navigation on a resolver.
@defer