execute method

void execute([
  1. TParam? param
])

Calls the wrapped handler function with an optional input parameter

Implementation

void execute([TParam? param]) async {
  // its valid to dispose a command anytime, so we have to make sure this
  // doesn't create an invalid state
  if (_isDisposing) {
    return;
  }
  if (Command.detailedStackTraces) {
    _traceBeforeExecute = Trace.current();
  }

  if (_restriction?.value == true) {
    _ifRestrictedExecuteInstead?.call(param);
    return;
  }
  if (!_canExecute.value) {
    return;
  }

  if (_isExecuting.value) {
    return;
  } else {
    _isExecuting.value = true;
  }

  _errors.value = null; // this will not trigger the listeners

  if (this is! CommandSync<TParam, TResult>) {
    _commandResult.value = CommandResult<TParam, TResult>(
      param,
      _includeLastResultInCommandResults ? value : null,
      null,
      true,
    );

    /// give the async notifications a chance to propagate
    await Future<void>.delayed(Duration.zero);
  }

  try {
    // lets play it save and check again if the command was disposed
    if (_isDisposing) {
      return;
    }
    await _execute(param);
  } catch (error, stacktrace) {
    StackTrace chain = Command.detailedStackTraces
        ? _improveStacktrace(stacktrace).terse
        : stacktrace;

    if (Command.assertionsAlwaysThrow && error is AssertionError) {
      Error.throwWithStackTrace(error, chain);
    }

    // ignore: deprecated_member_use_from_same_package
    if (kDebugMode && Command.debugErrorsThrowAlways) {
      Error.throwWithStackTrace(error, chain);
    }

    if (Command.reportAllExceptions) {
      Command.globalExceptionHandler?.call(
        CommandError(param, error, command: this, commandName: _debugName),
        chain,
      );
    }

    if (this is UndoableCommand) {
      final undoAble = this as UndoableCommand;
      if (undoAble._undoOnExecutionFailure) {
        undoAble._undo(error);
      }
    }

    _handleError(param, error, chain);
  } finally {
    if (!_isDisposing) {
      _isExecuting.value = false;
    }

    /// give the async notifications a chance to propagate
    await Future<void>.delayed(Duration.zero);
    if (_debugName != null) {
      Command.loggingHandler?.call(_debugName, _commandResult.value);
    }
  }
}