Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router unnecessarily waits for child resolvers before building parent component #14064

Closed
JohannesRudolph opened this issue Jan 23, 2017 · 8 comments

Comments

@JohannesRudolph
Copy link

JohannesRudolph commented Jan 23, 2017

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior
Consider a parent route (TestComponent) with ParentResolveGuard which has a child route with ChildResolveGuard (ChildComponent). When opening a deep link into the application, the router will wait for ParentResolveGuard and ChildResolveGuard to resolve before building the parent TestComponent.

Expected behavior
The router should only wait for ParentResolveGuard to complete before building the Parent route.

Minimal reproduction of the problem with instructions
Check out the following code:
https://github.com/JohannesRudolph/angular-cli-rxjs-repro/tree/resolver-repro

Run with angular-cli using ng serve and open in the browser. Observe the following output in the console when opening a deep link to ChildComponent = http://localhost:4200/#/child :

parent-resolve-guard.service.ts:15ParentResolveGuardService.resolve
child-resolve-guard.service.ts:13ChildResolveGuardService.resolve
// 10s wait here
test.component.ts:11TestComponent ctor
test.component.ts:15TestComponent ngOnInit
child.component.ts:11ChildComponent ctor
child.component.ts:15ChildComponent ngOnInit

I have inserted a 10s delay into the child resolver to make the behaviour more apparent.
With my code and fixed router behavior, a correct output would look like this:

parent-resolve-guard.service.ts:15ParentResolveGuardService.resolve
test.component.ts:11TestComponent ctor
test.component.ts:15TestComponent ngOnInit
child-resolve-guard.service.ts:13ChildResolveGuardService.resolve
// 10s wait here
child.component.ts:11ChildComponent ctor
child.component.ts:15ChildComponent ngOnInit

What is the motivation / use case for changing the behavior?
In my production app, the parent route listens for router events to display an animation during loading/unloading of lazy components. Due to current router behavior, the parent component does however not get loaded when opening a deep link into the application.

Please tell us about your environment:
yarn, vscode...

  • Angular version: 2.0.X
    2.4.4

  • Browser: all

  • Language: TypeScript 2.1

  • Node (for AoT issues): node --version =
    7.3

@brandonroberts
Copy link
Contributor

brandonroberts commented Jan 23, 2017

This is as designed. The router rendering process is synchronous, so all guards and resolves are run before that process begins. Guards and resolvers are blocking actions which is why your deep child route holds up the entire rendering until its complete.

@JohannesRudolph
Copy link
Author

That's a bit disappointing considering the API uses Observables and intuitively implies async rendering (at least to me). In any case, it makes the most sense then to leave long running and not automatically recoverable actions out of router resolve and activate guards.

@alex-che
Copy link

alex-che commented Nov 1, 2017

I was going to report the exact same issue when I found this one. The plunker demonstrates the problem.

I hardly see any reason to postpone rendering of a parent component until all the nested components got their resolvers completed. Parent component got everything to be rendered, so why wait?

If we had this implementation (rendering parents as soon as they are resolved), but for some reason wanted to postpone parent rendering until all the nested children are resolved, we could easily achieve this by listening to the Router ResolveEnd Event. But while we have this current implementation (blocking parents until all the children are resolved), I cannot see any workaround to achieve what I want.

Please, consider changing the implementation or at list adding an option to choose the needed behavior.

I also think that the issue #18975 is related.

@oliverjanik
Copy link

I have a similar problem. The issues seems to be 2-fold:

  1. Only components can declare new providers (not resolvers)
  2. I have a resolver that need a dependency that is provided by a parent component.

At the moment it's not possible, because resolvers don't wait for their parent components and the injection into resolvers is done using root injector.

This is very very inflexible and basically means resolvers can only use providers from the top level module.

@jasonaden
Copy link
Contributor

It appears this behaves as expected. If you still feel there is an issue, please provide further details in a new issue.

@oliverjanik
Copy link

oliverjanik commented Dec 20, 2017

Ignorant comment from angular maintainer as always.

I'm providing a case where default behaviour is undesirable. Your "expected" is a poor architectural choice and it could be improved.

It's not a bug it's a comment on poor design. But hey, it works as 'expected'.

You have 3 separate people suggesting an improvement in this thread with no actual downside and you just go ahead and close the discussion.

Sorry to bother you with our ordinary pleb issues. You ain't got no time for no feedback.

@simeyla
Copy link

simeyla commented Apr 4, 2019

It basically renders Resolve useless if you have something that may take a few seconds to load in a child component that has its own resolver.

Simpler case:

Your Account Page
    > Your Orders

I want 'Your Account' to display while orders are loading. I didn't think that'd be too much to ask.

Orders may take 5 seconds to load (yes that will be less in production but right now it's 5 seconds).

Resolve in general has proven to be not of much use unfortunately because of issues like this, and clumsy behavior with handling redirections (it really should work the same as AuthGuard that can return a UrlTree).

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 14, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants