fix(router): unsubscribe preload if the route has been preloaded by Wykks · Pull Request #26557 · angular/angular · GitHub
Skip to content

fix(router): unsubscribe preload if the route has been preloaded - #26557

Closed
Wykks wants to merge 1 commit into
angular:7.0.xfrom
Wykks:patch-1
Closed

Wykks wants to merge 1 commit into
angular:7.0.xfrom
Wykks:patch-1

Conversation

@Wykks

@Wykks Wykks commented Oct 18, 2018

Copy link
Copy Markdown

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

When a lazyloaded route is loaded with a user interaction for example, the observable returned by preload from a PreloadingStrategy is not unsubscribed. Which do not stop the preload strategy from loading the module again.

This basic preload strategy load the module twice if the user navigate to the route before 5 seconds:

@Injectable({
  providedIn: 'root'
})
export class PreloadAfterAWhile implements PreloadingStrategy {
  preload(route: Route, load: () => Observable<any>) {
    return of(true).pipe(delay(5000), switchMap(load));
  }
}

Reproduced here: https://stackblitz.com/edit/angular-preload-issue
Step to reproduce:

  1. Click on customers
  2. Look at the console "CustomersModule Loaded!"
  3. Wait at least 5 seconds
  4. The CustomersModule is loaded again, because the delay observable from the preload strategy has not been canceled.

What is the new behavior?

Cancel the preload observable if the route is loaded.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Also, the observable returned by load() is not cold, the loading start when the function is called, even if the observable is not subscribed. Is this intended ?


this.loader.load(loadChildren) should be wrapped inside an observable.

@Wykks
Wykks changed the base branch from 7.0.x to master October 25, 2018 12:01
@Wykks
Wykks changed the base branch from master to 7.0.x October 25, 2018 12:01
@benlesh
benlesh requested a review from jasonaden January 8, 2019 23:57
@ngbot ngbot Bot added this to the needsTriage milestone Jan 8, 2019
@jasonaden

Copy link
Copy Markdown
Contributor

Thanks for the PR. Can you please add a test? I would like to confirm this was failing in the past.

Looking at the code, I see a concatMap here. I haven't tested myself, but it looks to me like this will end up unsubscribing appropriately.

@jasonaden jasonaden left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about adding tests to confirm this is currently broken and this fixes it.

@Wykks

Wykks commented Jan 9, 2019

Copy link
Copy Markdown
Author

I already made stackblitz to reproduce the issue, so you should be able to confirm the issue there.
I have no idea how to make a test for that, but I'll try 👍

@benlesh benlesh added risk: low memory leak Issue related to a memory leak labels Jan 10, 2019
pgammans added a commit to pgammans/angular that referenced this pull request Apr 22, 2020
Add four test to check the interaction of PreloadingStrategy and normal
router navigation under differing scenarios.
Checking:
 * Prevention of duplicate loading of modules.
   related to angular#26557
 * Prevention of duplicate RouteConfigLoad(Start|End) events
   related to angular#22842
 * Ensuring preload strategy remains active for submodules if needed
   The selected preload strategy should still decide when to load submodules
 * Possibility of memory leak with unfinished preload subscription
   related to angular#26557
pgammans added a commit to pgammans/angular that referenced this pull request Apr 22, 2020
Store an observable on the route for the currently outstanding module
load factory.

The replaces the fix angular#26557 as that allowed overlapping requests to still
load the module twice.

Fixes angular#26557 angular#22842
pgammans added a commit to pgammans/angular that referenced this pull request Apr 23, 2020
Clear the stored loader promise so that subsequent load will try the fetch again.
The restores the same behaviour as before we cached the loader to fix  angular#26557
@atscott

atscott commented Aug 7, 2020

Copy link
Copy Markdown
Contributor

Closing due to the issues mentioned in #36760

  • By forcing the subscription to close if a module has a lazy sub-module then the these are passed to the PreloadingStrategy class as the observable has already terminated.
  • It doesn't actually prevent the load as the fetch may overlap with the preload fetch. Ie both the pre-loader and navigation can start a load both will finish .

@atscott atscott closed this Aug 7, 2020
@angular-automatic-lock-bot

Copy link
Copy Markdown

@angular-automatic-lock-bot angular-automatic-lock-bot Bot locked and limited conversation to collaborators Sep 7, 2020
pgammans added a commit to pgammans/angular that referenced this pull request Feb 11, 2021
Fix router to ensure that a route module is only loaded once especially
in relation to the use of preload strategies with delayed or partial
loading.

Add test to check the interaction of PreloadingStrategy and normal
router navigation under differing scenarios.
Checking:
 * Prevention of duplicate loading of modules.
   related to angular#26557
 * Prevention of duplicate RouteConfigLoad(Start|End) events
   related to angular#22842
 * Ensuring preload strategy remains active for submodules if needed
   The selected preload strategy should still decide when to load submodules
 * Possibility of memory leak with unfinished preload subscription
   related to angular#26557
 * Ensure that the stored loader promise is cleared so that subsequent
   load will try the fetch again.
 * Add error handle error from loadChildren
 * Ensure we handle error from with NgModule create

Fixes angular#26557 angular#22842 angular#26557
josephperrott pushed a commit that referenced this pull request Feb 11, 2021
#40389)

Fix router to ensure that a route module is only loaded once especially
in relation to the use of preload strategies with delayed or partial
loading.

Add test to check the interaction of PreloadingStrategy and normal
router navigation under differing scenarios.
Checking:
 * Prevention of duplicate loading of modules.
   related to #26557
 * Prevention of duplicate RouteConfigLoad(Start|End) events
   related to #22842
 * Ensuring preload strategy remains active for submodules if needed
   The selected preload strategy should still decide when to load submodules
 * Possibility of memory leak with unfinished preload subscription
   related to #26557
 * Ensure that the stored loader promise is cleared so that subsequent
   load will try the fetch again.
 * Add error handle error from loadChildren
 * Ensure we handle error from with NgModule create

Fixes #26557 #22842 #26557

PR Close #40389
josephperrott pushed a commit that referenced this pull request Feb 11, 2021
#40389)

Fix router to ensure that a route module is only loaded once especially
in relation to the use of preload strategies with delayed or partial
loading.

Add test to check the interaction of PreloadingStrategy and normal
router navigation under differing scenarios.
Checking:
 * Prevention of duplicate loading of modules.
   related to #26557
 * Prevention of duplicate RouteConfigLoad(Start|End) events
   related to #22842
 * Ensuring preload strategy remains active for submodules if needed
   The selected preload strategy should still decide when to load submodules
 * Possibility of memory leak with unfinished preload subscription
   related to #26557
 * Ensure that the stored loader promise is cleared so that subsequent
   load will try the fetch again.
 * Add error handle error from loadChildren
 * Ensure we handle error from with NgModule create

Fixes #26557 #22842 #26557

PR Close #40389
@atscott atscott reopened this Feb 11, 2021
@atscott atscott closed this Feb 11, 2021
josephperrott pushed a commit that referenced this pull request Feb 16, 2021
#40389)

Fix router to ensure that a route module is only loaded once especially
in relation to the use of preload strategies with delayed or partial
loading.

Add test to check the interaction of PreloadingStrategy and normal
router navigation under differing scenarios.
Checking:
 * Prevention of duplicate loading of modules.
   related to #26557
 * Prevention of duplicate RouteConfigLoad(Start|End) events
   related to #22842
 * Ensuring preload strategy remains active for submodules if needed
   The selected preload strategy should still decide when to load submodules
 * Possibility of memory leak with unfinished preload subscription
   related to #26557
 * Ensure that the stored loader promise is cleared so that subsequent
   load will try the fetch again.
 * Add error handle error from loadChildren
 * Ensure we handle error from with NgModule create

Fixes #26557 #22842 #26557

PR Close #40389
josephperrott pushed a commit that referenced this pull request Feb 16, 2021
#40389)

Fix router to ensure that a route module is only loaded once especially
in relation to the use of preload strategies with delayed or partial
loading.

Add test to check the interaction of PreloadingStrategy and normal
router navigation under differing scenarios.
Checking:
 * Prevention of duplicate loading of modules.
   related to #26557
 * Prevention of duplicate RouteConfigLoad(Start|End) events
   related to #22842
 * Ensuring preload strategy remains active for submodules if needed
   The selected preload strategy should still decide when to load submodules
 * Possibility of memory leak with unfinished preload subscription
   related to #26557
 * Ensure that the stored loader promise is cleared so that subsequent
   load will try the fetch again.
 * Add error handle error from loadChildren
 * Ensure we handle error from with NgModule create

Fixes #26557 #22842 #26557

PR Close #40389
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants