diff --git a/packages/service-worker/src/provider.ts b/packages/service-worker/src/provider.ts index 1cc28695db2..ca20ad30635 100644 --- a/packages/service-worker/src/provider.ts +++ b/packages/service-worker/src/provider.ts @@ -92,7 +92,14 @@ export function ngswAppInitializer(): void { // Don't return anything to avoid blocking the application until the SW is registered. // Catch and log the error if SW registration fails to avoid uncaught rejection warning. - readyToRegister.then(() => + readyToRegister.then(() => { + // If the registration strategy has resolved after the application has + // been explicitly destroyed by the user (e.g., by navigating away to + // another application), we simply should not register the worker. + if (appRef.destroyed) { + return; + } + navigator.serviceWorker .register(script, {scope: options.scope}) .catch((err) => @@ -103,8 +110,8 @@ export function ngswAppInitializer(): void { 'Service worker registration failed with: ' + err, ), ), - ), - ); + ); + }); }); } diff --git a/packages/service-worker/test/provider_spec.ts b/packages/service-worker/test/provider_spec.ts index fd0d11edcf9..867cb792c32 100644 --- a/packages/service-worker/test/provider_spec.ts +++ b/packages/service-worker/test/provider_spec.ts @@ -364,6 +364,17 @@ async function waitForReadyToRegister() { ); expect(swRegisterSpy).not.toHaveBeenCalled(); }); + + it('should not register service worker if app was destroyed before it was ready to register', async () => { + const registerSub = new Subject(); + configTestBedWithMockedStability(() => registerSub); + expect(swRegisterSpy).not.toHaveBeenCalled(); + // Given that the app is destroyed (e.g., by calling `ApplicationRef.destroy()`) + // before the `readyToRegister` promise resolves and `serviceWorker.register(...)` is called. + TestBed.resetTestingModule(); + await waitForReadyToRegister(); + expect(swRegisterSpy).not.toHaveBeenCalled(); + }); }); }); });