firstWhere 方法

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

查找此流中第一个符合 test 的元素。

返回一个 Future,该 Future 完成时包含此流中第一个使 test 返回 true 的元素。

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

如果在此流发射错误之前收到第一个匹配元素,返回的 Future 会以该错误完成,并且处理停止。

在接收到第一个匹配元素或错误后停止监听此流。

该方法在第一个匹配的元素后取消其订阅。这意味着单订阅(非广播)流在调用此方法后会关闭,并且不能在调用后重用。

如果发生错误,或者在此流完成之前未找到匹配项且未提供 orElse 函数,则返回的 Future 会以错误完成。

示例

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

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

实现

Future<T> firstWhere(bool test(T element), {T orElse()?}) {
  _Future<T> future = new _Future();
  StreamSubscription<T> subscription =
      this.listen(null, onError: future._completeError, onDone: () {
    if (orElse != null) {
      _runUserCode(orElse, future._complete, future._completeError);
      return;
    }
    try {
      // Sets stackTrace on error.
      throw IterableElementError.noElement();
    } catch (e, s) {
      _completeWithErrorCallback(future, e, s);
    }
  }, cancelOnError: true);

  subscription.onData((T value) {
    _runUserCode(() => test(value), (bool isMatch) {
      if (isMatch) {
        _cancelAndValue(subscription, future, value);
      }
    }, _cancelAndErrorClosure(subscription, future));
  });
  return future;
}