then<R> method
Null safety
Creates a new cancelable operation to be completed when this operation completes normally or as an error, or is cancelled.
If this operation completes normally the value is passed to onValue
and the returned operation is completed with the result.
If this operation completes as an error, and no onError
callback is
provided, the returned operation is completed with the same error and
stack trace.
If this operation completes as an error, and an onError
callback is
provided, the returned operation is completed with the result.
If this operation is canceled, and no onCancel
callback is provided,
the returned operation is canceled.
If this operation is canceled, and an onCancel
callback is provided,
the returned operation is completed with the result.
If the returned operation is canceled before this operation completes or
is canceled, the onValue
, onError
, and onCancel
callbacks will not
be invoked. If propagateCancel
is true
(the default) then this
operation is canceled as well. Pass false
if there are multiple
listeners on this operation and canceling the onValue
, onError
, and
onCancel
callbacks should not cancel the other listeners.
Implementation
CancelableOperation<R> then<R>(FutureOr<R> Function(T) onValue,
{FutureOr<R> Function(Object, StackTrace)? onError,
FutureOr<R> Function()? onCancel,
bool propagateCancel = true}) {
final completer =
CancelableCompleter<R>(onCancel: propagateCancel ? cancel : null);
// if `_completer._inner` completes before `completer` is cancelled
// call `onValue` or `onError` with the result, and complete `completer`
// with the result of that call (unless cancelled in the meantime).
//
// If `_completer._cancelCompleter` completes (always with a value)
// before `completer` is cancelled, then call `onCancel` (if supplied)
// with that that value and complete `completer` with the result of that
// call (unless cancelled in the meantime).
//
// If any of the callbacks throw synchronously, the `completer` is
// completed with that error.
//
// If no `onCancel` is provided, and `_completer._cancelCompleter`
// completes before `completer` is cancelled,
// then cancel `cancelCompleter`. (Cancelling twice is safe.)
_completer._inner?.future.then<void>((value) {
if (completer.isCanceled) return;
try {
completer.complete(onValue(value));
} catch (error, stack) {
completer.completeError(error, stack);
}
},
onError: onError == null
? completer.completeError // Is ignored if already cancelled.
: (Object error, StackTrace stack) {
if (completer.isCanceled) return;
try {
completer.complete(onError(error, stack));
} catch (error2, stack2) {
completer.completeError(error2, stack2);
}
});
_completer._cancelCompleter?.future.whenComplete(onCancel == null
? completer._cancel
: () {
if (completer.isCanceled) return;
try {
completer.complete(onCancel());
} catch (error, stack) {
completer.completeError(error, stack);
}
});
return completer.operation;
}