|
1 | 1 | import type {
|
2 | 2 | EndpointDefinitions,
|
| 3 | + QueryDefinition, |
3 | 4 | MutationDefinition,
|
4 | 5 | QueryArgFrom,
|
5 |
| - QueryDefinition, |
6 | 6 | ResultTypeFrom,
|
7 | 7 | } from '../endpointDefinitions'
|
8 | 8 | import { DefinitionType } from '../endpointDefinitions'
|
9 |
| -import type { MutationThunk, QueryThunk } from './buildThunks' |
10 |
| -import type { AnyAction, SerializedError, ThunkAction } from '@reduxjs/toolkit' |
11 |
| -import type { RootState, SubscriptionOptions } from './apiState' |
| 9 | +import type { QueryThunk, MutationThunk } from './buildThunks' |
| 10 | +import type { AnyAction, ThunkAction, SerializedError } from '@reduxjs/toolkit' |
| 11 | +import type { SubscriptionOptions, RootState } from './apiState' |
| 12 | +import { QueryStatus } from './apiState' |
12 | 13 | import type { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs'
|
13 | 14 | import type { Api, ApiContext } from '../apiTypes'
|
14 | 15 | import type { ApiEndpointQuery } from './module'
|
@@ -191,12 +192,10 @@ export function buildInitiate({
|
191 | 192 | api: Api<any, EndpointDefinitions, any, any>
|
192 | 193 | context: ApiContext<EndpointDefinitions>
|
193 | 194 | }) {
|
194 |
| - // keep track of running queries by id |
195 | 195 | const runningQueries: Record<
|
196 | 196 | string,
|
197 |
| - Record<string, QueryActionCreatorResult<any>> |
| 197 | + QueryActionCreatorResult<any> | undefined |
198 | 198 | > = {}
|
199 |
| - // keep track of running mutations by id |
200 | 199 | const runningMutations: Record<
|
201 | 200 | string,
|
202 | 201 | MutationActionCreatorResult<any> | undefined
|
@@ -225,20 +224,15 @@ export function buildInitiate({
|
225 | 224 | endpointDefinition,
|
226 | 225 | endpointName,
|
227 | 226 | })
|
228 |
| - // TODO(manuel) this is not really what we want, because we don't know which of those thunks will actually resolve to the correct result |
229 |
| - return Promise.all( |
230 |
| - Object.values(runningQueries[queryCacheKey] || {}) |
231 |
| - ).then((x) => x[0]) |
| 227 | + return runningQueries[queryCacheKey] |
232 | 228 | } else {
|
233 | 229 | return runningMutations[argOrRequestId]
|
234 | 230 | }
|
235 | 231 | }
|
236 | 232 |
|
237 | 233 | function getRunningOperationPromises() {
|
238 | 234 | return [
|
239 |
| - ...Object.values(runningQueries) |
240 |
| - .map((x) => Object.values(x)) |
241 |
| - .reduce((x, y) => x.concat(y)), |
| 235 | + ...Object.values(runningQueries), |
242 | 236 | ...Object.values(runningMutations),
|
243 | 237 | ].filter(<T>(t: T | undefined): t is T => !!t)
|
244 | 238 | }
|
@@ -281,20 +275,27 @@ Features like automatic cache collection, automatic refetching etc. will not be
|
281 | 275 | originalArgs: arg,
|
282 | 276 | queryCacheKey,
|
283 | 277 | })
|
| 278 | + const selector = ( |
| 279 | + api.endpoints[endpointName] as ApiEndpointQuery<any, any> |
| 280 | + ).select(arg) |
| 281 | + |
284 | 282 | const thunkResult = dispatch(thunk)
|
| 283 | + const stateAfter = selector(getState()) |
| 284 | + |
285 | 285 | middlewareWarning(getState)
|
286 | 286 |
|
287 | 287 | const { requestId, abort } = thunkResult
|
288 | 288 |
|
289 |
| - const prevThunks = Object.values(runningQueries?.[queryCacheKey] || {}) |
| 289 | + const skippedSynchronously = stateAfter.requestId !== requestId |
| 290 | + |
| 291 | + const runningQuery = runningQueries[queryCacheKey] |
290 | 292 |
|
291 |
| - let promises: Promise<any>[] = [...prevThunks, thunkResult] |
292 | 293 | const statePromise: QueryActionCreatorResult<any> = Object.assign(
|
293 |
| - Promise.all(promises).then(() => { |
294 |
| - return ( |
295 |
| - api.endpoints[endpointName] as ApiEndpointQuery<any, any> |
296 |
| - ).select(arg)(getState()) |
297 |
| - }), |
| 294 | + skippedSynchronously && !runningQuery |
| 295 | + ? Promise.resolve(stateAfter) |
| 296 | + : Promise.all([runningQuery, thunkResult]).then(() => |
| 297 | + selector(getState()) |
| 298 | + ), |
298 | 299 | {
|
299 | 300 | arg,
|
300 | 301 | requestId,
|
@@ -338,15 +339,13 @@ Features like automatic cache collection, automatic refetching etc. will not be
|
338 | 339 | }
|
339 | 340 | )
|
340 | 341 |
|
341 |
| - if (!runningQueries.hasOwnProperty(queryCacheKey)) { |
342 |
| - runningQueries[queryCacheKey] = {} |
| 342 | + if (!runningQuery && !skippedSynchronously) { |
| 343 | + runningQueries[queryCacheKey] = statePromise |
| 344 | + statePromise.then(() => { |
| 345 | + delete runningQueries[queryCacheKey] |
| 346 | + }) |
343 | 347 | }
|
344 | 348 |
|
345 |
| - runningQueries[queryCacheKey][requestId] = statePromise |
346 |
| - statePromise.then(() => { |
347 |
| - delete runningQueries?.[queryCacheKey]?.[requestId] |
348 |
| - }) |
349 |
| - |
350 | 349 | return statePromise
|
351 | 350 | }
|
352 | 351 | return queryAction
|
|
0 commit comments