| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011, 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 /** | |
| 6 * A [Future] is used to obtain a value sometime in the future. Receivers of a | |
| 7 * [Future] can obtain the value by passing a callback to [then]. For example: | |
| 8 * | |
| 9 * Future<int> future = getFutureFromSomewhere(); | |
| 10 * future.then((value) { | |
| 11 * print("I received the number $value"); | |
| 12 * }); | |
| 13 * | |
| 14 * A future may complete by *succeeding* (producing a value) or *failing* | |
| 15 * (producing an exception, which may be handled with [handleException]). | |
| 16 * Callbacks passed to [onComplete] will be invoked in either case. | |
| 17 * | |
| 18 * When a future completes, the following actions happen in order: | |
| 19 * | |
| 20 * 1. if the future suceeded, handlers registered with [then] are called. | |
| 21 * 2. if the future failed, handlers registered with [handleException] are | |
| 22 * called in sequence, until one returns true. | |
| 23 * 3. handlers registered with [onComplete] are called | |
| 24 * 4. if the future failed, and at least one handler was registered with | |
| 25 * [then], and no handler registered with [handleException] returned | |
| 26 * [:true:], then the exception is thrown. | |
| 27 * | |
| 28 * Use a [Completer] to create and change the state of a [Future]. | |
| 29 */ | |
| 30 interface Future<T> default FutureImpl<T> { | |
| 31 | |
| 32 /** A future whose value is immediately available. */ | |
| 33 Future.immediate(T value); | |
| 34 | |
| 35 /** The value provided. Throws an exception if [hasValue] is false. */ | |
| 36 T get value(); | |
| 37 | |
| 38 /** | |
| 39 * Exception that occurred ([:null:] if no exception occured). This property | |
| 40 * throws a [FutureNotCompleteException] if it is used before this future is | |
| 41 * completes. | |
| 42 */ | |
| 43 Object get exception(); | |
| 44 | |
| 45 /** | |
| 46 * The stack trace object associated with the exception that occurred. This | |
| 47 * throws a [FutureNotCompleteException] if it is used before the future | |
| 48 * completes. Returns [:null:] if the future completed successfully or a | |
| 49 * stack trace wasn't provided with the exception when it occurred. | |
| 50 */ | |
| 51 Object get stackTrace(); | |
| 52 | |
| 53 /** | |
| 54 * Whether the future is complete (either the value is available or there was | |
| 55 * an exception). | |
| 56 */ | |
| 57 bool get isComplete(); | |
| 58 | |
| 59 /** | |
| 60 * Whether the value is available (meaning [isComplete] is true, and there was | |
| 61 * no exception). | |
| 62 */ | |
| 63 bool get hasValue(); | |
| 64 | |
| 65 /** | |
| 66 * When this future is complete (either with a value or with an exception), | |
| 67 * then [complete] is called with the future. | |
| 68 * If [complete] throws an exception, it is ignored. | |
| 69 */ | |
| 70 void onComplete(void complete(Future<T> future)); | |
| 71 | |
| 72 /** | |
| 73 * If this future is complete and has a value, then [onValue] is called | |
| 74 * with the value. | |
| 75 */ | |
| 76 void then(void onSuccess(T value)); | |
| 77 | |
| 78 /** | |
| 79 * If this future is complete and has an exception, then call [onException]. | |
| 80 * | |
| 81 * If [onException] returns true, then the exception is considered handled. | |
| 82 * | |
| 83 * If [onException] does not return true (or [handleException] was never | |
| 84 * called), then the exception is not considered handled. In that case, if | |
| 85 * there were any calls to [then], then the exception will be thrown when the | |
| 86 * value is set. | |
| 87 * | |
| 88 * In most cases it should not be necessary to call [handleException], | |
| 89 * because the exception associated with this [Future] will propagate | |
| 90 * naturally if the future's value is being consumed. Only call | |
| 91 * [handleException] if you need to do some special local exception handling | |
| 92 * related to this particular Future's value. | |
| 93 */ | |
| 94 void handleException(bool onException(Object exception)); | |
| 95 | |
| 96 /** | |
| 97 * A future representing [transformation] applied to this future's value. | |
| 98 * | |
| 99 * When this future gets a value, [transformation] will be called on the | |
| 100 * value, and the returned future will receive the result. | |
| 101 * | |
| 102 * If an exception occurs (received by this future, or thrown by | |
| 103 * [transformation]) then the returned future will receive the exception. | |
| 104 * | |
| 105 * You must not add exception handlers to [this] future prior to calling | |
| 106 * transform, and any you add afterwards will not be invoked. | |
| 107 */ | |
| 108 Future transform(transformation(T value)); | |
| 109 | |
| 110 /** | |
| 111 * A future representing an asynchronous transformation applied to this | |
| 112 * future's value. [transformation] must return a Future. | |
| 113 * | |
| 114 * When this future gets a value, [transformation] will be called on the | |
| 115 * value. When the resulting future gets a value, the returned future | |
| 116 * will receive it. | |
| 117 * | |
| 118 * If an exception occurs (received by this future, thrown by | |
| 119 * [transformation], or received by the future returned by [transformation]) | |
| 120 * then the returned future will receive the exception. | |
| 121 * | |
| 122 * You must not add exception handlers to [this] future prior to calling | |
| 123 * chain, and any you add afterwards will not be invoked. | |
| 124 */ | |
| 125 Future chain(Future transformation(T value)); | |
| 126 } | |
| 127 | |
| 128 | |
| 129 /** | |
| 130 * A [Completer] is used to produce [Future]s and supply their value when it | |
| 131 * becomes available. | |
| 132 * | |
| 133 * A service that provides values to callers, and wants to return [Future]s can | |
| 134 * use a [Completer] as follows: | |
| 135 * | |
| 136 * Completer completer = new Completer(); | |
| 137 * // send future object back to client... | |
| 138 * return completer.future; | |
| 139 * ... | |
| 140 * | |
| 141 * // later when value is available, call: | |
| 142 * completer.complete(value); | |
| 143 * | |
| 144 * // alternatively, if the service cannot produce the value, it | |
| 145 * // can provide an exception: | |
| 146 * completer.completeException(exception); | |
| 147 * | |
| 148 */ | |
| 149 interface Completer<T> default CompleterImpl<T> { | |
| 150 | |
| 151 Completer(); | |
| 152 | |
| 153 /** The future that will contain the value produced by this completer. */ | |
| 154 Future get future(); | |
| 155 | |
| 156 /** Supply a value for [future]. */ | |
| 157 void complete(T value); | |
| 158 | |
| 159 /** | |
| 160 * Indicate in [future] that an exception occured while trying to produce its | |
| 161 * value. The argument [exception] should not be [:null:]. A [stackTrace] | |
| 162 * object can be provided as well to give the user information about where | |
| 163 * the error occurred. If omitted, it will be [:null:]. | |
| 164 */ | |
| 165 void completeException(Object exception, [Object stackTrace]); | |
| 166 } | |
| 167 | |
| 168 /** Thrown when reading a future's properties before it is complete. */ | |
| 169 class FutureNotCompleteException implements Exception { | |
| 170 FutureNotCompleteException() {} | |
| 171 String toString() => "Exception: future has not been completed"; | |
| 172 } | |
| 173 | |
| 174 /** | |
| 175 * Thrown if a completer tries to set the value on a future that is already | |
| 176 * complete. | |
| 177 */ | |
| 178 class FutureAlreadyCompleteException implements Exception { | |
| 179 FutureAlreadyCompleteException() {} | |
| 180 String toString() => "Exception: future already completed"; | |
| 181 } | |
| 182 | |
| 183 | |
| 184 /** | |
| 185 * [Futures] holds additional utility functions that operate on [Future]s (for | |
| 186 * example, waiting for a collection of Futures to complete). | |
| 187 */ | |
| 188 class Futures { | |
| 189 | |
| 190 /** | |
| 191 * Returns a future which will complete once all the futures in a list are | |
| 192 * complete. If any of the futures in the list completes with an exception, | |
| 193 * the resulting future also completes with an exception. (The value of the | |
| 194 * returned future will be a list of all the values that were produced.) | |
| 195 */ | |
| 196 static Future<List> wait(List<Future> futures) { | |
| 197 if (futures.isEmpty()) { | |
| 198 return new Future<List>.immediate(const []); | |
| 199 } | |
| 200 | |
| 201 Completer completer = new Completer<List>(); | |
| 202 Future<List> result = completer.future; | |
| 203 int remaining = futures.length; | |
| 204 List values = new List(futures.length); | |
| 205 | |
| 206 // As each future completes, put its value into the corresponding | |
| 207 // position in the list of values. | |
| 208 for (int i = 0; i < futures.length; i++) { | |
| 209 // TODO(mattsh) - remove this after bug | |
| 210 // http://code.google.com/p/dart/issues/detail?id=333 is fixed. | |
| 211 int pos = i; | |
| 212 Future future = futures[pos]; | |
| 213 future.then((Object value) { | |
| 214 values[pos] = value; | |
| 215 if (--remaining == 0 && !result.isComplete) { | |
| 216 completer.complete(values); | |
| 217 } | |
| 218 }); | |
| 219 future.handleException((exception) { | |
| 220 if (!result.isComplete) { | |
| 221 completer.completeException(exception, future.stackTrace); | |
| 222 } | |
| 223 return true; | |
| 224 }); | |
| 225 } | |
| 226 return result; | |
| 227 } | |
| 228 } | |
| OLD | NEW |