@@ -11,6 +11,16 @@ import type {
1111
1212export type ReferenceCacheCollection = never
1313
14+ function isObjectEmpty ( obj : Record < any , any > ) {
15+ // Apparently a for..in loop is faster than `Object.keys()` here:
16+ // https://stackoverflow.com/a/59787784/62937
17+ for ( let k in obj ) {
18+ // If there is at least one key, it's not empty
19+ return false
20+ }
21+ return true
22+ }
23+
1424declare module '../../endpointDefinitions' {
1525 interface QueryExtraOptions <
1626 TagTypes extends string ,
@@ -38,6 +48,15 @@ export const THIRTY_TWO_BIT_MAX_TIMER_SECONDS = 2_147_483_647 / 1_000 - 1
3848export const build : SubMiddlewareBuilder = ( { reducerPath, api, context } ) => {
3949 const { removeQueryResult, unsubscribeQueryResult } = api . internalActions
4050
51+ function anySubscriptionsRemainingForKey (
52+ queryCacheKey : string ,
53+ api : SubMiddlewareApi
54+ ) {
55+ const subscriptions =
56+ api . getState ( ) [ reducerPath ] . subscriptions [ queryCacheKey ]
57+ return ! ! subscriptions && ! isObjectEmpty ( subscriptions )
58+ }
59+
4160 return ( mwApi ) => {
4261 const currentRemovalTimeouts : QueryStateMeta < TimeoutId > = { }
4362
@@ -103,18 +122,18 @@ export const build: SubMiddlewareBuilder = ({ reducerPath, api, context }) => {
103122 Math . min ( keepUnusedDataFor , THIRTY_TWO_BIT_MAX_TIMER_SECONDS )
104123 )
105124
106- const currentTimeout = currentRemovalTimeouts [ queryCacheKey ]
107- if ( currentTimeout ) {
108- clearTimeout ( currentTimeout )
109- }
110- currentRemovalTimeouts [ queryCacheKey ] = setTimeout ( ( ) => {
111- const subscriptions =
112- api . getState ( ) [ reducerPath ] . subscriptions [ queryCacheKey ]
113- if ( ! subscriptions || Object . keys ( subscriptions ) . length === 0 ) {
114- api . dispatch ( removeQueryResult ( { queryCacheKey } ) )
125+ if ( ! anySubscriptionsRemainingForKey ( queryCacheKey , api ) ) {
126+ const currentTimeout = currentRemovalTimeouts [ queryCacheKey ]
127+ if ( currentTimeout ) {
128+ clearTimeout ( currentTimeout )
115129 }
116- delete currentRemovalTimeouts ! [ queryCacheKey ]
117- } , finalKeepUnusedDataFor * 1000 )
130+ currentRemovalTimeouts [ queryCacheKey ] = setTimeout ( ( ) => {
131+ if ( ! anySubscriptionsRemainingForKey ( queryCacheKey , api ) ) {
132+ api . dispatch ( removeQueryResult ( { queryCacheKey } ) )
133+ }
134+ delete currentRemovalTimeouts ! [ queryCacheKey ]
135+ } , finalKeepUnusedDataFor * 1000 )
136+ }
118137 }
119138 }
120139}
0 commit comments