@@ -39,26 +39,29 @@ export interface FirebaseAccessToken {
3939 */
4040export class FirebaseAppInternals {
4141 private cachedToken_ : FirebaseAccessToken ;
42+ private promiseToCachedToken_ : Promise < FirebaseAccessToken > ;
4243 private tokenListeners_ : Array < ( token : string ) => void > ;
44+ private isRefreshing : boolean ;
4345
4446 // eslint-disable-next-line @typescript-eslint/naming-convention
4547 constructor ( private credential_ : Credential ) {
4648 this . tokenListeners_ = [ ] ;
49+ this . isRefreshing = false ;
4750 }
4851
4952 public getToken ( forceRefresh = false ) : Promise < FirebaseAccessToken > {
5053 if ( forceRefresh || this . shouldRefresh ( ) ) {
51- return this . refreshToken ( ) ;
54+ this . promiseToCachedToken_ = this . refreshToken ( ) ;
5255 }
53-
54- return Promise . resolve ( this . cachedToken_ ) ;
56+ return this . promiseToCachedToken_
5557 }
5658
5759 public getCachedToken ( ) : FirebaseAccessToken | null {
5860 return this . cachedToken_ || null ;
5961 }
6062
6163 private refreshToken ( ) : Promise < FirebaseAccessToken > {
64+ this . isRefreshing = true ;
6265 return Promise . resolve ( this . credential_ . getAccessToken ( ) )
6366 . then ( ( result ) => {
6467 // Since the developer can provide the credential implementation, we want to weakly verify
@@ -108,11 +111,15 @@ export class FirebaseAppInternals {
108111 }
109112
110113 throw new FirebaseAppError ( AppErrorCodes . INVALID_CREDENTIAL , errorMessage ) ;
111- } ) ;
114+ } )
115+ . finally ( ( ) => {
116+ this . isRefreshing = false ;
117+ } )
112118 }
113119
114120 private shouldRefresh ( ) : boolean {
115- return ! this . cachedToken_ || ( this . cachedToken_ . expirationTime - Date . now ( ) ) <= TOKEN_EXPIRY_THRESHOLD_MILLIS ;
121+ return ( ! this . cachedToken_ || ( this . cachedToken_ . expirationTime - Date . now ( ) ) <= TOKEN_EXPIRY_THRESHOLD_MILLIS )
122+ && ! this . isRefreshing ;
116123 }
117124
118125 /**
0 commit comments