doWhile static method
Performs an operation repeatedly until it returnsfalse.
The operation,action, may be either synchronous or asynchronous.
The operation is called repeatedly as long as it returns either theboolvaluetrue or aFuture<bool> which completes with the valuetrue.
If a call toaction returnsfalse or aFuture that completes tofalse, iteration ends and the future returned bydoWhile is completedwith anull value.
If a call toaction throws or a future returned byaction completeswith an error, iteration ends and the future returned bydoWhilecompletes with the same error.
Calls toaction may happen at any time,including immediately after callingdoWhile.The only restriction is a new call toaction won't happen beforethe previous call has returned, and if it returned aFuture<bool>, notuntil that future has completed.
Example:
void main() async { var value = 0; await Future.doWhile(() async { value++; await Future.delayed(const Duration(seconds: 1)); if (value == 3) { print('Finished with $value'); return false; } return true; });}// Outputs: 'Finished with 3'Implementation
static Future<void> doWhile(FutureOr<bool> action()) { _Future<void> doneSignal = _Future<void>(); late void Function(bool) nextIteration; // Bind this callback explicitly so that each iteration isn't bound in the // context of all the previous iterations' callbacks. // This avoids, e.g., deeply nested stack traces from the stack trace // package. nextIteration = Zone.current.bindUnaryCallbackGuarded((bool keepGoing) { while (keepGoing) { FutureOr<bool> result; try { result = action(); } catch (error, stackTrace) { // Cannot use `_completeWithErrorCallback` because it completes // the future synchronously. doneSignal._asyncCompleteErrorObject( _interceptCaughtError(error, stackTrace), ); return; } if (result is Future<bool>) { result.then(nextIteration, onError: doneSignal._completeError); return; } keepGoing = result; } doneSignal._complete(null); }); nextIteration(true); return doneSignal;}