1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'dart:async'; |
6 | |
7 | /// A [Future] whose [then] implementation calls the callback immediately. |
8 | /// |
9 | /// This is similar to [Future.value], except that the value is available in |
10 | /// the same event-loop iteration. |
11 | /// |
12 | /// ⚠ This class is useful in cases where you want to expose a single API, where |
13 | /// you normally want to have everything execute synchronously, but where on |
14 | /// rare occasions you want the ability to switch to an asynchronous model. **In |
15 | /// general use of this class should be avoided as it is very difficult to debug |
16 | /// such bimodal behavior.** |
17 | /// |
18 | /// A [SynchronousFuture] will never complete with an error. |
19 | class SynchronousFuture<T> implements Future<T> { |
20 | /// Creates a synchronous future. |
21 | /// |
22 | /// See also: |
23 | /// |
24 | /// * [Future.value] for information about creating a regular |
25 | /// [Future] that completes with a value. |
26 | SynchronousFuture(this._value); |
27 | |
28 | final T _value; |
29 | |
30 | @override |
31 | Stream<T> asStream() { |
32 | final StreamController<T> controller = StreamController<T>(); |
33 | controller.add(_value); |
34 | controller.close(); |
35 | return controller.stream; |
36 | } |
37 | |
38 | @override |
39 | Future<T> catchError(Function onError, { bool Function(Object error)? test }) => Completer<T>().future; |
40 | |
41 | @override |
42 | Future<R> then<R>(FutureOr<R> Function(T value) onValue, { Function? onError }) { |
43 | final FutureOr<R> result = onValue(_value); |
44 | if (result is Future<R>) { |
45 | return result; |
46 | } |
47 | return SynchronousFuture<R>(result); |
48 | } |
49 | |
50 | @override |
51 | Future<T> timeout(Duration timeLimit, { FutureOr<T> Function()? onTimeout }) { |
52 | return Future<T>.value(_value).timeout(timeLimit, onTimeout: onTimeout); |
53 | } |
54 | |
55 | @override |
56 | Future<T> whenComplete(FutureOr<dynamic> Function() action) { |
57 | try { |
58 | final FutureOr<dynamic> result = action(); |
59 | if (result is Future) { |
60 | return result.then<T>((dynamic value) => _value); |
61 | } |
62 | return this; |
63 | } catch (e, stack) { |
64 | return Future<T>.error(e, stack); |
65 | } |
66 | } |
67 | } |
68 | |