@@ -4,6 +4,7 @@ import type { FetchErrorCauses, IConfigFetcher, IFetchResponse } from "./ConfigF
4
4
import { FetchError , FetchResult , FetchStatus } from "./ConfigFetcher" ;
5
5
import { RedirectMode } from "./ConfigJson" ;
6
6
import { Config , ProjectConfig } from "./ProjectConfig" ;
7
+ import { isPromiseLike } from "./Utils" ;
7
8
8
9
/** Contains the result of an `IConfigCatClient.forceRefresh` or `IConfigCatClient.forceRefreshAsync` operation. */
9
10
export class RefreshResult {
@@ -75,6 +76,7 @@ function nameOfConfigServiceStatus(value: ConfigServiceStatus): string {
75
76
export abstract class ConfigServiceBase < TOptions extends OptionsBase > {
76
77
private status : ConfigServiceStatus ;
77
78
79
+ private pendingCacheSyncUp : Promise < ProjectConfig > | null = null ;
78
80
private pendingFetch : Promise < FetchResult > | null = null ;
79
81
80
82
protected readonly cacheKey : string ;
@@ -103,7 +105,7 @@ export abstract class ConfigServiceBase<TOptions extends OptionsBase> {
103
105
abstract getConfig ( ) : Promise < ProjectConfig > ;
104
106
105
107
async refreshConfigAsync ( ) : Promise < [ RefreshResult , ProjectConfig ] > {
106
- const latestConfig = await this . options . cache . get ( this . cacheKey ) ;
108
+ const latestConfig = await this . syncUpWithCache ( ) ;
107
109
if ( ! this . isOffline ) {
108
110
const [ fetchResult , config ] = await this . refreshConfigCoreAsync ( latestConfig ) ;
109
111
return [ RefreshResult . from ( fetchResult ) , config ] ;
@@ -147,13 +149,8 @@ export abstract class ConfigServiceBase<TOptions extends OptionsBase> {
147
149
}
148
150
149
151
private fetchAsync ( lastConfig : ProjectConfig ) : Promise < FetchResult > {
150
- return this . pendingFetch ??= ( async ( ) => {
151
- try {
152
- return await this . fetchLogicAsync ( lastConfig ) ;
153
- } finally {
154
- this . pendingFetch = null ;
155
- }
156
- } ) ( ) ;
152
+ return this . pendingFetch ??= this . fetchLogicAsync ( lastConfig )
153
+ . finally ( ( ) => this . pendingFetch = null ) ;
157
154
}
158
155
159
156
private async fetchLogicAsync ( lastConfig : ProjectConfig ) : Promise < FetchResult > {
@@ -305,7 +302,20 @@ export abstract class ConfigServiceBase<TOptions extends OptionsBase> {
305
302
abstract getCacheState ( cachedConfig : ProjectConfig ) : ClientCacheState ;
306
303
307
304
protected syncUpWithCache ( ) : ProjectConfig | Promise < ProjectConfig > {
308
- return this . options . cache . get ( this . cacheKey ) ;
305
+ if ( this . pendingCacheSyncUp ) {
306
+ return this . pendingCacheSyncUp ;
307
+ }
308
+
309
+ const syncResult = this . options . cache . get ( this . cacheKey ) ;
310
+ if ( ! isPromiseLike ( syncResult ) ) {
311
+ return syncResult ;
312
+ }
313
+
314
+ const syncUpAndFinish = syncResult
315
+ . finally ( ( ) => this . pendingCacheSyncUp = null ) ;
316
+
317
+ this . pendingCacheSyncUp = syncResult ;
318
+ return syncUpAndFinish ;
309
319
}
310
320
311
321
protected async waitForReadyAsync ( initialCacheSyncUp : ProjectConfig | Promise < ProjectConfig > ) : Promise < ClientCacheState > {
0 commit comments