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

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

Closed
wants to merge 1 commit into from

Conversation

Wykks
Copy link

@Wykks Wykks commented Oct 18, 2018

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 ?

private loadModuleFactory(loadChildren: LoadChildren): Observable<NgModuleFactory<any>> {
if (typeof loadChildren === 'string') {
return from(this.loader.load(loadChildren));
} else {
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t: any) => {
if (t instanceof NgModuleFactory) {
return of (t);
} else {
return from(this.compiler.compileModuleAsync(t));
}
}));
}
}
}

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
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.

Copy link
Contributor

@jasonaden jasonaden left a comment

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
Copy link
Author

Wykks commented Jan 9, 2019

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 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 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 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
Copy link
Contributor

atscott commented Aug 7, 2020

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

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 7, 2020
pgammans added a commit to pgammans/angular that referenced this pull request Jan 11, 2021
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
 * 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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 11, 2021
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 Jan 11, 2021
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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 13, 2021
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
 * 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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 13, 2021
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 Jan 13, 2021
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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 13, 2021
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
 * 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
 * Add error handle error from loadChildren
 * Ensure we handle error from with NgModule create
pgammans added a commit to pgammans/angular that referenced this pull request Jan 13, 2021
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 Jan 13, 2021
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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 14, 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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 16, 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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 28, 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
pgammans added a commit to pgammans/angular that referenced this pull request Jan 28, 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
pgammans added a commit to pgammans/angular that referenced this pull request Feb 1, 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
pgammans added a commit to pgammans/angular that referenced this pull request Feb 1, 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
pgammans added a commit to pgammans/angular that referenced this pull request Feb 5, 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
pgammans added a commit to pgammans/angular that referenced this pull request Feb 5, 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
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.

None yet

5 participants