singleWhere 方法

Future<T> singleWhere(
  1. bool test(
    1. T element
    ), {
  2. T orElse()?,
})

在该流中找到匹配 test 的单个元素。

返回一个将完成该流中满足 test 返回 true 的单个元素的 Future。

如果在流完成之前未找到此类元素,并且提供了 orElse 函数,则调用 orElse 的结果成为 Future 的值。如果 orElse 抛出异常,则返回的 Future 将以该错误完成。

只能有一个元素匹配。如果找到多个匹配元素,则会抛出错误,无论是否传递了 orElse

如果此流在任何时候发出错误,则返回的 Future 将以该错误完成,并且取消订阅。

在流完成之前不能提供非错误结果。

类似于 lastWhere,不同之处在于如果在此流中发生多个匹配元素,则这是一个错误。

示例

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.

实现

Future<T> singleWhere(bool test(T element), {T orElse()?}) {
  _Future<T> future = new _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;
    }
    try {
      throw IterableElementError.noElement();
    } catch (e, s) {
      _completeWithErrorCallback(future, e, s);
    }
  }, cancelOnError: true);

  subscription.onData((T value) {
    _runUserCode(() => test(value), (bool isMatch) {
      if (isMatch) {
        if (foundResult) {
          try {
            throw IterableElementError.tooMany();
          } catch (e, s) {
            _cancelAndErrorWithReplacement(subscription, future, e, s);
          }
          return;
        }
        foundResult = true;
        result = value;
      }
    }, _cancelAndErrorClosure(subscription, future));
  });
  return future;
}