Skip to content

Commit 2035fe8

Browse files
committed
Correctly wait for service worker registration to become active before allowing any operations on it.
1 parent ffbf5a6 commit 2035fe8

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

.changeset/neat-beans-rescue.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/messaging': patch
3+
---
4+
5+
Fix an issue where PushManager.subscribe() is called too soon after registering the default service worker.

packages/messaging/src/helpers/registerDefaultSw.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,40 @@ export async function registerDefaultSw(
3939
messaging.swRegistration.update().catch(() => {
4040
/* it is non blocking and we don't care if it failed */
4141
});
42+
await waitForRegistrationActive(messaging.swRegistration);
4243
} catch (e) {
4344
throw ERROR_FACTORY.create(ErrorCode.FAILED_DEFAULT_REGISTRATION, {
4445
browserErrorMessage: (e as Error)?.message
4546
});
4647
}
4748
}
49+
50+
/**
51+
* Waits for registration to become active. MDN documentation claims that
52+
* a service worker registration should be ready to use after awaiting
53+
* navigator.serviceWorker.register() but that doesn't seem to be the case in
54+
* practice, causing the SDK to throw errors when calling
55+
* swRegistration.pushManager.subscribe() too soon after register(). The only
56+
* solution seems to be waiting for the service worker registration `state`
57+
* to become "active".
58+
*/
59+
async function waitForRegistrationActive(
60+
registration: ServiceWorkerRegistration
61+
): Promise<void> {
62+
return new Promise<void>((resolve, reject) => {
63+
if (registration.active) {
64+
resolve();
65+
}
66+
const incomingSw = registration.installing || registration.waiting;
67+
if (incomingSw) {
68+
incomingSw.onstatechange = ev => {
69+
if ((ev.target as ServiceWorker)?.state === 'activated') {
70+
incomingSw.onstatechange = null;
71+
resolve();
72+
}
73+
};
74+
} else {
75+
reject(new Error('No incoming service worker found.'));
76+
}
77+
});
78+
}

0 commit comments

Comments
 (0)