fix: Read from cache first on cacheAndNetwork
When fetch policy is cacheAndNetwork, we now return cache and then
fetch from network, if the cached result is available). If not
we fetch from network.
MODIFY
packages/graphql/lib/src/core/query_manager.dart
packages/graphql/lib/src/core/query_manager.dart
@@ -146,11 +146,22 @@ class QueryManager {
Future<QueryResult<TParsed>> query<TParsed>(
QueryOptions<TParsed> options) async {
- final result = await fetchQuery(_oneOffOpId, options);
+ final results = fetchQueryAsMultiSourceResult(_oneOffOpId, options);
+ final eagerResult = results.eagerResult;
+ final networkResult = results.networkResult;
+ if (options.fetchPolicy != FetchPolicy.cacheAndNetwork ||
+ eagerResult.isLoading) {
+ final result = networkResult ?? eagerResult;
+ await result;
maybeRebroadcastQueries();
-
return result;
}
+ maybeRebroadcastQueries();
+ if (networkResult is Future<QueryResult<TParsed>>) {
+ networkResult.then((value) => maybeRebroadcastQueries());
+ }
+ return eagerResult;
+ }
Future<QueryResult<TParsed>> mutate<TParsed>(
MutationOptions<TParsed> options) async {

MODIFY
packages/graphql/test/fetch_policy_test.dart
packages/graphql/test/fetch_policy_test.dart
@@ -65,10 +65,10 @@ void main() {
group('query', () {
// TODO cacheFirst code path: Return result from cache. Only fetch from network if cached result is not available.
- // TODO cacheAndNetwork code path: Return result from cache first (if it exists), then return network result once it's available.
// TODO cacheOnly code path: Return result from cache if available, fail otherwise.
// TODO noCache code path: Return result from network, fail if network call doesn't succeed, don't save to cache.
// TODO networkOnly code path: Return result from network, fail if network call doesn't succeed, save to cache.
+
test('switch to cacheOnly returns cached data', () async {
final _options = QueryOptions(
fetchPolicy: FetchPolicy.cacheAndNetwork,
@@ -117,6 +117,50 @@ void main() {
expect(cacheResult.exception, isNull);
expect(cacheResult.data, equals(repoData));
});
+ test('cacheAndNetwork returns from cache (if exists)', () async {
+ final _options = QueryOptions(
+ fetchPolicy: FetchPolicy.cacheAndNetwork,
+ document: parseString(readRepositories),
+ variables: <String, dynamic>{
+ 'nRepositories': 42,
+ },
+ );
+ final repoData = readRepositoryData(withTypenames: true);
+
+ when(
+ link.request(any),
+ ).thenAnswer(
+ (_) => Stream.fromIterable([
+ Response(data: repoData),
+ ]),
+ );
+
+ final QueryResult r = await client.query(_options);
+
+ verify(
+ link.request(
+ Request(
+ operation: Operation(
+ document: parseString(readRepositories),
+ //operationName: 'ReadRepositories',
+ ),
+ variables: <String, dynamic>{
+ 'nRepositories': 42,
+ },
+ context: Context(),
+ ),
+ ),
+ );
+
+ expect(r.exception, isNull);
+ expect(r.data, equals(repoData));
+ expect(r.source, QueryResultSource.network);
+
+ final QueryResult cacheResult = await client.query(_options);
+ expect(cacheResult.exception, isNull);
+ expect(cacheResult.data, equals(repoData));
+ expect(cacheResult.source, equals(QueryResultSource.cache));
+ });
});
});
}

fix: Read from cache first on cacheAndNetwork

When fetch policy is cacheAndNetwork, we now return cache and then
fetch from network, if the cached result is available). If not
we fetch from network.