diff --git a/src/database/database-internal.ts b/src/database/database-internal.ts index 66d8db883c..9ad9e5bb51 100644 --- a/src/database/database-internal.ts +++ b/src/database/database-internal.ts @@ -116,18 +116,15 @@ export class DatabaseService { // eslint-disable-next-line @typescript-eslint/no-unused-vars private onTokenChange(_: string): void { - this.appInternal.INTERNAL.getToken() - .then((token) => { - const delayMillis = token.expirationTime - TOKEN_REFRESH_THRESHOLD_MILLIS - Date.now(); - // If the new token is set to expire soon (unlikely), do nothing. Somebody will eventually - // notice and refresh the token, at which point this callback will fire again. - if (delayMillis > 0) { - this.scheduleTokenRefresh(delayMillis); - } - }) - .catch((err) => { - console.error('Unexpected error while attempting to schedule a token refresh:', err); - }); + const token = this.appInternal.INTERNAL.getCachedToken(); + if (token) { + const delayMillis = token.expirationTime - TOKEN_REFRESH_THRESHOLD_MILLIS - Date.now(); + // If the new token is set to expire soon (unlikely), do nothing. Somebody will eventually + // notice and refresh the token, at which point this callback will fire again. + if (delayMillis > 0) { + this.scheduleTokenRefresh(delayMillis); + } + } } private scheduleTokenRefresh(delayMillis: number): void { diff --git a/src/firebase-app.ts b/src/firebase-app.ts index 88947bec4c..c9e9588d59 100644 --- a/src/firebase-app.ts +++ b/src/firebase-app.ts @@ -74,6 +74,10 @@ export class FirebaseAppInternals { return Promise.resolve(this.cachedToken_); } + public getCachedToken(): FirebaseAccessToken | null { + return this.cachedToken_ || null; + } + private refreshToken(): Promise { return Promise.resolve(this.credential_.getAccessToken()) .then((result) => { @@ -97,6 +101,8 @@ export class FirebaseAppInternals { if (!this.cachedToken_ || this.cachedToken_.accessToken !== token.accessToken || this.cachedToken_.expirationTime !== token.expirationTime) { + // Update the cache before firing listeners. Listeners may directly query the + // cached token state. this.cachedToken_ = token; this.tokenListeners_.forEach((listener) => { listener(token.accessToken); diff --git a/test/unit/database/database.spec.ts b/test/unit/database/database.spec.ts index 739dcbccfc..763041262e 100644 --- a/test/unit/database/database.spec.ts +++ b/test/unit/database/database.spec.ts @@ -211,9 +211,7 @@ describe('Database', () => { }); }); - // Currently doesn't work as expected since onTokenChange() can force a token refresh - // by calling getToken(). Skipping for now. - xit('should not reschedule when the token is about to expire in 5 minutes', () => { + it('should not reschedule when the token is about to expire in 5 minutes', () => { database.getDatabase(); return mockApp.INTERNAL.getToken() .then((token1) => {