description

# singleWhere method

Future<T> singleWhere(

1. bool test(
   1. T element
   ), {
2. T orElse()?,

})

Finds the single element in this stream matching `test`.

Returns a future that is completed with the single element of this stream for which `test` returns `true`.

If no such element is found before this stream is done, and an `orElse` function is provided, the result of calling `orElse` becomes the value of the future. If `orElse` throws, the returned future is completed with that error.

Only one element may match. If more than one matching element is found an error is thrown, regardless of whether `orElse` was passed.

If this stream emits an error at any point, the returned future is completed with that error, and the subscription is canceled.

A non-error result cannot be provided before this stream is done.

Similar to lastWhere, except that it is an error if more than one matching element occurs in this stream.

Example:

    var result = await Stream.fromIterable([1, 2, 3, 6, 9, 12])
        .singleWhere((element) => element % 4 == 0, orElse: () => -1);
    print(result); // 12

    result = await Stream.fromIterable([2, 6, 8, 12, 24, 32])
        .singleWhere((element) => element % 9 == 0, orElse: () => -1);
    print(result); // -1

    result = await Stream.fromIterable([2, 6, 8, 12, 24, 32])
        .singleWhere((element) => element % 6 == 0, orElse: () => -1);
    // Throws.

## Implementation

    Future<T> singleWhere(bool test(T element), {T orElse()?}) {
      @pragma('vm:awaiter-link')
      _Future<T> future = _Future<T>();
      late T result;
      bool foundResult = false;
      StreamSubscription<T> subscription = this.listen(
        null,
        onError: future._completeError,
        onDone: () {
          if (foundResult) {
            future._complete(result);
            return;
          }
          if (orElse != null) {
            _runUserCode(orElse, future._complete, future._completeError);
            return;
          }
          var stack = StackTrace.current;
          var error = IterableElementError.noElement();
          _trySetStackTrace(error, stack);
          _completeWithErrorCallback(future, error, stack);
        },
        cancelOnError: true,
      );

      subscription.onData((T value) {
        _runUserCode(() => test(value), (bool isMatch) {
          if (isMatch) {
            if (foundResult) {
              var stack = StackTrace.current;
              var error = IterableElementError.tooMany();
              _trySetStackTrace(error, stack);
              _cancelAndErrorWithReplacement(subscription, future, error, stack);
              return;
            }
            foundResult = true;
            result = value;
          }
        }, _cancelAndErrorClosure(subscription, future));
      });
      return future;
    }