Skip to content

Commit ecfb48f

Browse files
committed
Read from cache again in ObservableQuery#getCurrentResult.
This partially reverts two commits from PR #5565, preserving related improvements that have happened in the meantime: * Revert "Remove partial field from ApolloCurrentQueryResult type." This reverts commit ca2cef6. * Revert "Stop reading from cache in ObservableQuery#getCurrentResult." This reverts commit 01376a3. One of the motivations behind the original changes was to lay the foundations for eventually supporting asynchronous (Promise-based) cache reads, but that form of asynchrony is no longer a goal of Apollo Client 3.0 or any planned future version, so there's not as much benefit to weakening getCurrentResult in this way. On the other hand, allowing getCurrentResult to read synchronously from the cache ensures that custom field read functions can return new results immediately, which helps with issues like #5782. Immediate cache reads have also been the behavior of Apollo Client for much longer than #5565, which makes this change appealing from an ease-of-upgrading perspective.
1 parent 617b1db commit ecfb48f

File tree

4 files changed

+62
-35
lines changed

4 files changed

+62
-35
lines changed

src/core/ObservableQuery.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { isNonEmptyArray } from '../utilities/common/arrays';
2020

2121
export type ApolloCurrentQueryResult<T> = ApolloQueryResult<T> & {
2222
error?: ApolloError;
23+
partial?: boolean;
2324
};
2425

2526
export interface FetchMoreOptions<
@@ -131,8 +132,12 @@ export class ObservableQuery<
131132
}
132133

133134
public getCurrentResult(): ApolloCurrentQueryResult<TData> {
134-
const { lastResult, lastError } = this;
135-
const { fetchPolicy } = this.options;
135+
const {
136+
lastResult,
137+
lastError,
138+
options: { fetchPolicy },
139+
} = this;
140+
136141
const isNetworkFetchPolicy =
137142
fetchPolicy === 'network-only' ||
138143
fetchPolicy === 'no-cache';
@@ -145,7 +150,7 @@ export class ObservableQuery<
145150

146151
const result: ApolloCurrentQueryResult<TData> = {
147152
data: !lastError && lastResult && lastResult.data || void 0,
148-
error: this.lastError,
153+
error: lastError,
149154
loading: isNetworkRequestInFlight(networkStatus),
150155
networkStatus,
151156
stale: lastResult ? lastResult.stale : false,
@@ -155,6 +160,9 @@ export class ObservableQuery<
155160
return result;
156161
}
157162

163+
const { data, partial } = this.queryManager.getCurrentQueryResult(this);
164+
Object.assign(result, { data, partial });
165+
158166
const queryStoreValue = this.queryManager.queryStore.get(this.queryId);
159167
if (queryStoreValue) {
160168
const { networkStatus } = queryStoreValue;
@@ -176,11 +184,10 @@ export class ObservableQuery<
176184
// the original `ObservableQuery`. We'll update the observable query
177185
// variables here to match, so retrieving from the cache doesn't fail.
178186
if (queryStoreValue.variables) {
179-
this.options.variables = {
187+
this.variables = this.options.variables = {
180188
...this.options.variables,
181189
...(queryStoreValue.variables as TVariables),
182190
};
183-
this.variables = this.options.variables;
184191
}
185192

186193
Object.assign(result, {
@@ -193,7 +200,10 @@ export class ObservableQuery<
193200
}
194201
}
195202

196-
this.updateLastResult(result);
203+
if (!partial) {
204+
result.stale = false;
205+
this.updateLastResult(result);
206+
}
197207

198208
return result;
199209
}

src/core/QueryManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ export class QueryManager<TStore> {
10521052
this.queries.delete(queryId);
10531053
}
10541054

1055-
private getCurrentQueryResult<T>(
1055+
public getCurrentQueryResult<T>(
10561056
observableQuery: ObservableQuery<T>,
10571057
optimistic: boolean = true,
10581058
): {

src/core/__tests__/ObservableQuery.ts

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,7 @@ describe('ObservableQuery', () => {
14501450
loading: false,
14511451
networkStatus: 7,
14521452
stale: false,
1453+
partial: false,
14531454
});
14541455
resolve();
14551456
});
@@ -1459,6 +1460,7 @@ describe('ObservableQuery', () => {
14591460
data: undefined,
14601461
networkStatus: 1,
14611462
stale: false,
1463+
partial: true,
14621464
});
14631465

14641466
setTimeout(
@@ -1468,12 +1470,40 @@ describe('ObservableQuery', () => {
14681470
data: undefined,
14691471
networkStatus: 1,
14701472
stale: false,
1473+
partial: true,
14711474
});
14721475
}),
14731476
0,
14741477
);
14751478
});
14761479

1480+
itAsync('returns results from the store immediately', (resolve, reject) => {
1481+
const queryManager = mockQueryManager(reject, {
1482+
request: { query, variables },
1483+
result: { data: dataOne },
1484+
});
1485+
1486+
return queryManager.query({ query, variables }).then((result: any) => {
1487+
expect(stripSymbols(result)).toEqual({
1488+
data: dataOne,
1489+
loading: false,
1490+
networkStatus: 7,
1491+
stale: false,
1492+
});
1493+
const observable = queryManager.watchQuery({
1494+
query,
1495+
variables,
1496+
});
1497+
expect(stripSymbols(observable.getCurrentResult())).toEqual({
1498+
data: dataOne,
1499+
loading: true,
1500+
networkStatus: NetworkStatus.loading,
1501+
stale: false,
1502+
partial: false,
1503+
});
1504+
}).then(resolve, reject);
1505+
});
1506+
14771507
itAsync('returns errors from the store immediately', (resolve, reject) => {
14781508
const queryManager = mockQueryManager(reject, {
14791509
request: { query, variables },
@@ -1563,7 +1593,7 @@ describe('ObservableQuery', () => {
15631593
}).then(resolve, reject);
15641594
});
15651595

1566-
itAsync('returns partial data from the store', (resolve, reject) => {
1596+
itAsync('returns partial data from the store immediately', (resolve, reject) => {
15671597
const superQuery = gql`
15681598
query superQuery($id: ID!) {
15691599
people_one(id: $id) {
@@ -1600,10 +1630,11 @@ describe('ObservableQuery', () => {
16001630
});
16011631

16021632
expect(observable.getCurrentResult()).toEqual({
1603-
data: void 0,
1633+
data: dataOne,
16041634
loading: true,
16051635
networkStatus: 1,
16061636
stale: false,
1637+
partial: true,
16071638
});
16081639

16091640
// we can use this to trigger the query
@@ -1618,28 +1649,19 @@ describe('ObservableQuery', () => {
16181649

16191650
if (handleCount === 1) {
16201651
expect(subResult).toEqual({
1621-
data: void 0,
1652+
data: dataOne,
16221653
loading: true,
16231654
networkStatus: 1,
16241655
stale: false,
16251656
});
16261657

16271658
} else if (handleCount === 2) {
1628-
expect(subResult).toEqual({
1629-
data: dataOne,
1630-
loading: false,
1631-
networkStatus: 7,
1632-
stale: false,
1633-
});
1634-
1635-
} else if (handleCount === 3) {
16361659
expect(subResult).toEqual({
16371660
data: superDataOne,
16381661
loading: false,
16391662
networkStatus: 7,
16401663
stale: false,
16411664
});
1642-
16431665
resolve();
16441666
}
16451667
});
@@ -1670,6 +1692,7 @@ describe('ObservableQuery', () => {
16701692
loading: true,
16711693
networkStatus: 1,
16721694
stale: false,
1695+
partial: false,
16731696
});
16741697

16751698
subscribeAndCount(reject, observable, (handleCount, subResult) => {
@@ -1679,29 +1702,21 @@ describe('ObservableQuery', () => {
16791702
networkStatus,
16801703
} = observable.getCurrentResult();
16811704

1682-
expect(subResult).toEqual({
1683-
data,
1684-
loading,
1685-
networkStatus,
1686-
stale: false,
1687-
});
1688-
16891705
if (handleCount === 1) {
1690-
expect(stripSymbols(subResult)).toEqual({
1691-
data: void 0,
1692-
loading: true,
1693-
networkStatus: NetworkStatus.loading,
1706+
expect(subResult).toEqual({
1707+
data,
1708+
loading,
1709+
networkStatus,
16941710
stale: false,
1711+
partial: false,
16951712
});
1696-
16971713
} else if (handleCount === 2) {
16981714
expect(stripSymbols(subResult)).toEqual({
16991715
data: dataTwo,
17001716
loading: false,
1701-
networkStatus: NetworkStatus.ready,
1717+
networkStatus: 7,
17021718
stale: false,
17031719
});
1704-
17051720
resolve();
17061721
}
17071722
});
@@ -1727,12 +1742,12 @@ describe('ObservableQuery', () => {
17271742
variables,
17281743
fetchPolicy: 'no-cache',
17291744
});
1730-
17311745
expect(stripSymbols(observable.getCurrentResult())).toEqual({
17321746
data: undefined,
17331747
loading: true,
17341748
networkStatus: 1,
17351749
stale: false,
1750+
partial: false,
17361751
});
17371752

17381753
subscribeAndCount(reject, observable, (handleCount, subResult) => {
@@ -1748,6 +1763,7 @@ describe('ObservableQuery', () => {
17481763
loading,
17491764
networkStatus,
17501765
stale: false,
1766+
partial: false,
17511767
});
17521768
} else if (handleCount === 2) {
17531769
expect(stripSymbols(subResult)).toEqual({

src/react/data/QueryData.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ export class QueryData<TData, TVariables> extends OperationData {
353353
} else {
354354
// Fetch the current result (if any) from the store.
355355
const currentResult = this.currentObservable.query!.getCurrentResult();
356-
const { loading, networkStatus, errors } = currentResult;
356+
const { loading, partial, networkStatus, errors } = currentResult;
357357
let { error, data } = currentResult;
358358

359359
// Until a set naming convention for networkError and graphQLErrors is
@@ -390,6 +390,7 @@ export class QueryData<TData, TVariables> extends OperationData {
390390
const { partialRefetch } = options;
391391
if (
392392
partialRefetch &&
393+
partial &&
393394
(!data || Object.keys(data).length === 0) &&
394395
fetchPolicy !== 'cache-only'
395396
) {

0 commit comments

Comments
 (0)