Why use a resolver with Angular

I like the idea of resolver s.

You can say that:
- for this route, you expect some data to be downloaded first
- you can just have a really simple component without visible ones (like getting data from this.route.snapshot.data )

So resolvers make a lot of sense.

BUT:
- You do not change the URL or display the requested component until you receive the actual response. Thus, you cannot (simply) show the user that something is happening by rendering your component and show as much as you can (as recommended, for a shell application with PWA). This means that if there is a poor connection, your user can simply wait without visually indicating what has been going on for a long time.
- If you use a recognizer on a route with a parameter, take the users/1 example, it will work fine for the first time. But if you go to users/2 , nothing will happen unless you start using another observable: this.route.data.subscribe()

So, it seems that resolvers can be useful for getting some data, but in practice I would not use them in the case of a slow network and especially for routes with parameters.

Am I missing something? Is there a way to use them with these real limitations?

+28
source share
4 answers

Resolver: runs before the user is redirected to a new page.

Whenever you need to get data before initializing a component, the correct way to do this is to use a recognizer. Resolver acts synchronously, i.e. The resolver will wait for the asynchronous call to complete, and only after processing the asynchronous call will it be redirected to the corresponding URL. Thus, component initialization will wait for the callback to complete. Thus, if you want to do something (calling a service), even before the component is initialized, you are in the right place.

Sample scenario: I was working on a project in which the user would pass the file name for upload to the URL. Based on the name passed, we make an asynchronous call to ngOnInit and get the file. But the problem is that if the user passes the wrong name in the URL, our service will try to get a file that does not exist on the server. We have 2 options in this scenario:

Option 1: get a list of valid file names in ngOnInit, and then call the actual service to retrieve the file (if the file name is valid). Both of these calls must be synchronous .

Option 2: Retrieve a list of valid file names in the resolver, verify the correct file name in the URL, and retrieve the file data.

Option 2 is the best choice, as the recognizer handles the synchronization of calls.

Important :: Use a resolver if you want to receive data before the user is redirected to the URL. Resolver may include service calls that provide us with the data needed to load the next page.

+4
source

The recognition tool gives you a trap at the beginning of the navigation of the router and allows you to control the navigation attempt. This gives you more freedom, but not many hard and fast rules.

You do not need to use the resolution result in your component. You can simply use determination as a hook. This is my preferred use for the reasons you indicated. Using the result in your component is much simpler, but it has these synchronous tradeoffs.

For example, if you use something like Material or Cdk, you can send a Download dialog box to display a progress bar at the beginning of the resolution, and then close the dialog box after the resolution is complete. Like this:

 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 are using ngrx , you can do something similar by submitting actions in the resolution process.

When you use Resolve protection in this way, there is no particular reason to use Resolve protection instead of CanActivate protection. This choice comes down to semantics. I find it more obvious to use CanActivate authentication and initiate data retrieval from Resolve. When these topics can be mixed, it becomes an arbitrary choice.

+2
source

This is why I would use a resolver:

  • Single responsibility, my component needs some data, in some cases this data is provided by the cache or state, in the event of a loss, I need to first get it and transfer it directly without changing my component. Example : on the search results page with the list myapp.com/lists go to one item in the list myapp.com/lists/1 , which shows the details of this item, you do not need to retrieve data already performed by the search. Then, suppose you go directly to myapp.com/lists/1 you need to get, and then go to the component.
  • Isolate your component from router logic.
  • My component does not have to control the loading state of the fetch request, it is only responsible for displaying data

Consider the recognizer as middleware between your application and your component, you can control the loading view in the parent component, which includes the <router-outlet> .

+1
source

In fact, I'm currently refactoring an application that uses a lot of recognizers, I thought about them a lot and I think that the biggest problem with them is that they modify the data, you have to display the data received from activeRoute. In other words, this adds complexity and problems to the maintenance of the application, while the direct implementation of the service does not have this problem .... In addition, since the resolvers are synchronous, in most cases they really slow down the work of users ...

0
source

Source: https://habr.com/ru/post/1275647/


All Articles