fix(service-worker): do not register service worker if app is destroyed before it is ready to register (#61101)

In this commit, we check whether the application is destroyed before calling `serviceWorker.register(...)`. We should not register the worker because other resources will not be available.

PR Close #61101
This commit is contained in:
arturovt 2025-05-02 19:43:53 +03:00 committed by Andrew Scott
parent ad8931cb49
commit ce916fe08c
2 changed files with 21 additions and 3 deletions

View file

@ -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,
),
),
),
);
);
});
});
}

View file

@ -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<void>();
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();
});
});
});
});