thenOperation<R> method

CancelableOperation<R> thenOperation<R>(
  1. FutureOr<void> onValue(
    1. T,
    2. CancelableCompleter<R>
    ), {
  2. FutureOr<void> onError(
    1. Object,
    2. StackTrace,
    3. CancelableCompleter<R>
    )?,
  3. FutureOr<void> onCancel(
    1. CancelableCompleter<R>
    )?,
  4. bool propagateCancel = true,
})

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 with a CancelableCompleter controlling the returned operation.

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 error and stack trace are passed to onError with a CancelableCompleter controlling the returned operation.

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 onCancel callback is called with a CancelableCompleter controlling the returned operation.

At most one of onValue, onError, or onCancel will be called. If any of onValue, onError, or onCancel throw a synchronous error, or return a Future that completes as an error, the error will be forwarded through the returned operation.

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> thenOperation<R>(
    FutureOr<void> Function(T, CancelableCompleter<R>) onValue,
    {FutureOr<void> Function(Object, StackTrace, CancelableCompleter<R>)?
        onError,
    FutureOr<void> Function(CancelableCompleter<R>)? 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) async {
    if (completer.isCanceled) return;
    try {
      await onValue(value, completer);
    } catch (error, stack) {
      completer.completeError(error, stack);
    }
  },
      onError: onError == null
          ? completer.completeError // Is ignored if already cancelled.
          : (Object error, StackTrace stack) async {
              if (completer.isCanceled) return;
              try {
                await onError(error, stack, completer);
              } catch (error2, stack2) {
                completer.completeError(
                    error2, identical(error, error2) ? stack : stack2);
              }
            });
  _completer._cancelCompleter?.future.whenComplete(onCancel == null
      ? completer._cancel
      : () async {
          if (completer.isCanceled) return;
          try {
            await onCancel(completer);
          } catch (error, stack) {
            completer.completeError(error, stack);
          }
        });
  return completer.operation;
}