Skip to content

Commit

Permalink
feat: Cache parsed data
Browse files Browse the repository at this point in the history
  • Loading branch information
budde377 committed Jun 3, 2023
1 parent 0953e94 commit aa81251
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 4 deletions.
24 changes: 20 additions & 4 deletions packages/graphql/lib/src/core/query_result.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ final _eagerSources = {
class QueryResult<TParsed extends Object?> {
@protected
QueryResult.internal({
this.data,
Map<String, dynamic>? data,
this.exception,
this.context = const Context(),
required this.parserFn,
required this.source,
}) : timestamp = DateTime.now();
}) : timestamp = DateTime.now() {
_data = data;
}

factory QueryResult({
required BaseOptions<TParsed> options,
Expand Down Expand Up @@ -99,7 +101,17 @@ class QueryResult<TParsed extends Object?> {
QueryResultSource? source;

/// Response data
Map<String, dynamic>? data;
Map<String, dynamic>? get data {
return _data;
}

set data(Map<String, dynamic>? data) {
_data = data;
_cachedParsedData = null;
}

Map<String, dynamic>? _data;
TParsed? _cachedParsedData;

/// Response context. Defaults to an empty `Context()`
Context context;
Expand Down Expand Up @@ -137,11 +149,15 @@ class QueryResult<TParsed extends Object?> {
TParsed? get parsedData {
final data = this.data;
final parserFn = this.parserFn;
final cachedParsedData = _cachedParsedData;

if (data == null) {
return null;
}
return parserFn(data);
if (cachedParsedData != null) {
return cachedParsedData;
}
return _cachedParsedData = parserFn(data);
}

@override
Expand Down
76 changes: 76 additions & 0 deletions packages/graphql/test/query_result_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import 'package:gql/language.dart';
import 'package:graphql/client.dart';
import 'package:test/test.dart';

void main() {
group('Query result', () {
test('data parsing should work with null data', () {
int runTimes = 0;
final result = QueryResult<String?>(
options: QueryOptions(
document: parseString('query { bar }'),
parserFn: (data) {
runTimes++;
return data['bar'] as String?;
},
),
source: QueryResultSource.network,
data: null,
);
expect(result.parsedData, equals(null));
expect(runTimes, equals(0));
});
test('data parsing should work with data', () {
int runTimes = 0;
final bar = "Bar";
final result = QueryResult<String?>(
options: QueryOptions(
document: parseString('query { bar }'),
parserFn: (data) {
runTimes++;
return data['bar'] as String?;
},
),
source: QueryResultSource.network,
data: {"bar": bar},
);
expect(result.parsedData, equals(bar));
expect(result.parsedData, equals(bar));
expect(runTimes, equals(1));
});
test('data parsing should work with data', () {
final bar = "Bar";
final result = QueryResult<String?>(
options: QueryOptions(
document: parseString('query { bar }'),
parserFn: (data) {
return data['bar'] as String?;
},
),
source: QueryResultSource.network,
data: {"bar": bar},
);
expect(result.data, equals({"bar": bar}));
});
test('updating data should clear parsed data', () {
int runTimes = 0;
final bar = "Bar";
final result = QueryResult<String?>(
options: QueryOptions(
document: parseString('query { bar }'),
parserFn: (data) {
runTimes++;
return data['bar'] as String?;
},
),
source: QueryResultSource.network,
data: {"bar": bar},
);
expect(result.parsedData, equals(bar));
expect(runTimes, equals(1));
result.data = {"bar": bar};
expect(result.parsedData, equals(bar));
expect(runTimes, equals(2));
});
});
}

0 comments on commit aa81251

Please # to comment.