get method
Returns a value from the cache for a given TIdentifier
.
If the TIdentifier
is not present in the cache the value returned by the
given valueFactory
is added to the cache and returned.
All calls to get await a call to the current caching strategy's
CachingStrategy.onDidGet lifecycle method before returning the cached value.
If the Cache does not contain an instance for the given TIdentifier
,
the given valueFactory
is called and a CacheContext event is emitted on
the didUpdate stream. A call to get that returns a cached value does
not emit this event as the Cache has not changed.
Calls to get are evaluated synchronously and will return the future value
established by the first call to get. This allows calls to get to
return the same value regardless of completion of asynchronous calls to the
current caching strategy's CachingStrategy.onDidGet lifecycle method or
valueFactory
.
var a = cache.get('id', _superLongCall);
var b = cache.get('id', _superLongCall);
var c = cache.get('id', _superLongCall);
// The futures in this list will all resolve to the same instance,
// which was returned by `_superLongCall` the first time `get` was called.
var values = Future.wait([a, b, c]);
If the Cache isOrWillBeDisposed then a StateError is thrown.
Implementation
@mustCallSuper
Future<TValue> get(TIdentifier id, Func<TValue> valueFactory) {
_log.finest('get id: $id');
_throwWhenDisposed('get');
_cachingStrategy.onWillGet(id);
_isReleased[id] = false;
// Await any pending cached futures
if (_cache.containsKey(id)) {
return _cache[id]!.then((TValue value) async {
await _cachingStrategy.onDidGet(id, value);
return value;
});
}
// Install Future value
final Completer<TValue> completer = Completer<TValue>();
_cache[id] = completer.future;
try {
final TValue value = valueFactory.call();
_cachingStrategy.onDidGet(id, value).then((Null _) {
_didUpdateController.add(CacheContext(id, value));
completer.complete(value);
});
} catch (error, stackTrace) {
completer.completeError(error, stackTrace);
}
return _cache[id]!;
}