Line data Source code
1 : // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 : // for details. All rights reserved. Use of this source code is governed by a 3 : // BSD-style license that can be found in the LICENSE file. 4 : 5 : import 'dart:async'; 6 : 7 : /// A class for running an asynchronous function exactly once and caching its 8 : /// result. 9 : /// 10 : /// An `AsyncMemoizer` is used when some function may be run multiple times in 11 : /// order to get its result, but it only actually needs to be run once for its 12 : /// effect. To memoize the result of an async function, you can create a 13 : /// memoizer outside the function (for example as an instance field if you want 14 : /// to memoize the result of a method), and then wrap the function's body in a 15 : /// call to [runOnce]. 16 : /// 17 : /// This is useful for methods like `close()` and getters that need to do 18 : /// asynchronous work. For example: 19 : /// 20 : /// ```dart 21 : /// class SomeResource { 22 : /// final _closeMemo = AsyncMemoizer(); 23 : /// 24 : /// Future close() => _closeMemo.runOnce(() { 25 : /// // ... 26 : /// }); 27 : /// } 28 : /// ``` 29 : class AsyncMemoizer<T> { 30 : /// The future containing the method's result. 31 : /// 32 : /// This can be accessed at any time, and will fire once [runOnce] is called. 33 0 : Future<T> get future => _completer.future; 34 : final _completer = Completer<T>(); 35 : 36 : /// Whether [runOnce] has been called yet. 37 0 : bool get hasRun => _completer.isCompleted; 38 : 39 : /// Runs the function, [computation], if it hasn't been run before. 40 : /// 41 : /// If [runOnce] has already been called, this returns the original result. 42 0 : Future<T> runOnce(FutureOr<T> Function() computation) { 43 0 : if (!hasRun) _completer.complete(Future.sync(computation)); 44 0 : return future; 45 : } 46 : }