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
5import '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.
19class 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