Why would you use a resolver with Angular

北城余情 提交于 2019-11-29 22:55:18

Resolver: It gets executed even before the user is routed to new page.

Whenever you need to get the data before the component initialization, the right way to do this is to use resolver. Resolver acts synchronously i.e. resolver will wait for async call to complete and only after processing the async call, it will route to the respective URL. Thus, the component initialization will wait till the callback is completed. Thus, if you want to do something (service call), even before the component is initialized, you have come to right place.

Example Scenario: I was working on the project where user would pass the name of file to be loaded in the URL. Based on the name passed we would do the async call in ngOnInit and get the file. But the problem with this is, if user passes the incorrect name in URL, our service would try to fetch the file which does not exists on the server. We have 2 option in such scenario:

Option 1: To get the list of valid filenames in ngOnInit, and then call the actual service to fetch the file (If file name is valid). Both of these calls should be synchronous.

Option 2: Fetch the list of valid filenames in the resolver, check whether filename in URL is valid or not, and then fetch the file data.

Option 2 is a better choice, since resolver handles the synchronicity of calls.

Important:: Use resolver when you want to fetch the data even before the user is routed to the URL. Resolver could include service calls which would bring us the data required to load the next page.

The resolver gives you a hook near the start of router navigation and it lets you control the navigation attempt. This gives you a lot of freedom, but not a lot of hard and fast rules.

You don't have to use the result of the resolve in your component. You can just use the resolve as a hook. This is my preferred way of using it for the reasons you've cited. Using the result in your component is much simpler, but it has those synchronous trade-offs.

For example, if you're using something like Material or Cdk, you could dispatch a "loading" dialog to display a progress indicator at the start of the resolve, then close the dialog when the resolve concludes. Like so:

constructor(route: ActivatedRouteSnapshot, myService: MyService, dialog: MatDialog) {}

resolve() {
    const dialogRef = this.dialog.open(ProgressComponent);
    return this.myService.getMyImportantData().pipe(
        tap(data => this.myService.storeData(data)),
        tap(() => dialogRef.close()),
        map(() => true),
        catchError(err => of(false))
    );
}

If you're using ngrx, you could do something similar by dispatching actions while the resolve is in progress.

When you're using the Resolve guard in this fashion, there's not a particularly strong reason to use the Resolve guard instead of the CanActivate guard. That choice comes down to semantics. I find it more obvious to gate authentication on CanActivate and initiate data retrieval from Resolve. When those topics are allowed to blend it becomes an abritrary choice.

This is why I would use a resolver:

  • Single Responsibility, my component needs some data, in some cases this data are provided by a cache or state, when missing I need first to fetch them, and pass directly, without changing my component. Example: A Search Result page with a list myapp.com/lists, navigate to one element of the list myapp.com/lists/1, showing the details of that element, no need to fetch the data, already done by the search. Then let suppose you navigate directly to myapp.com/lists/1 you need to fetch and then navigate to the component
  • Isolate your component from router logic
  • My component should not manage the loading state of a fetch request, it's only responsibility is showing the data

Think to the resolver as a middleware between your app and your component, you can manage the loading view in the parent component, where <router-outlet> is included.

I actually currently refactoring an app which uses a lot of resolvers, thought about them a lot and think the biggest issue with them is that they mutate the data, you have to map the data fetched from activatedRoute. In other words it adds complexities and problems in maintaining the app, whereas direct service injection doesn't have this issue.... Furthermore because resolvers are synchronous, in most cases the really slow down user experience...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!