Skip to content

Commit b847d05

Browse files
committed
fix: simplify waitForActivation with settled flag pattern
refactor to use idempotent succeed/fail helpers that prevent double resolution. check worker state after adding listener to close race condition window where worker could activate before listener attached.
1 parent 747c239 commit b847d05

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

src/lib/register-service-worker.ts

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,39 @@ export async function registerServiceWorker (): Promise<ServiceWorkerRegistratio
1515

1616
async function waitForActivation (swRegistration: ServiceWorkerRegistration): Promise<ServiceWorkerRegistration> {
1717
return new Promise((resolve, reject) => {
18+
let settled = false
19+
20+
const succeed = (): void => {
21+
if (settled) { return }
22+
settled = true
23+
clearTimeout(timeoutId)
24+
resolve(swRegistration)
25+
}
26+
27+
const fail = (msg: string): void => {
28+
if (settled) { return }
29+
settled = true
30+
clearTimeout(timeoutId)
31+
reject(new Error(msg))
32+
}
33+
1834
const timeoutId = setTimeout(() => {
19-
reject(new Error('Service worker failed to activate within 30 seconds. Refresh the page to retry.'))
35+
fail('Service worker failed to activate within 30 seconds. Refresh the page to retry.')
2036
}, 30_000)
2137

22-
const onStateChange = (e: Event): void => {
23-
const sw = e.target as ServiceWorker
24-
if (sw.state === 'activated') {
25-
clearTimeout(timeoutId)
26-
resolve(swRegistration)
27-
} else if (sw.state === 'redundant') {
28-
clearTimeout(timeoutId)
29-
reject(new Error('Service worker became redundant. Refresh the page to retry.'))
30-
}
38+
const trackWorker = (sw: ServiceWorker | null): void => {
39+
if (sw == null) { return }
40+
sw.addEventListener('statechange', () => {
41+
if (sw.state === 'activated') { succeed() } else if (sw.state === 'redundant') { fail('Service worker became redundant. Refresh the page to retry.') }
42+
})
43+
if (sw.state === 'activated') { succeed() }
3144
}
3245

33-
// track workers that may already be installing or waiting
34-
swRegistration.installing?.addEventListener('statechange', onStateChange)
35-
swRegistration.waiting?.addEventListener('statechange', onStateChange)
46+
trackWorker(swRegistration.installing)
47+
trackWorker(swRegistration.waiting)
48+
trackWorker(swRegistration.active)
3649
swRegistration.addEventListener('updatefound', () => {
37-
swRegistration.installing?.addEventListener('statechange', onStateChange)
50+
trackWorker(swRegistration.installing)
3851
})
3952
})
4053
}

0 commit comments

Comments
 (0)