Dart - 获取流的最后一个或第一个值

Dart - Get the last or the first value of a stream

我有一个流,我需要使用这个流的最后一个值,如果这个流没有发出任何值,我需要等待第一个值。我只想使用一次这个值。正确的做法是什么?

听起来你想要一个流发出的最近事件(这可能是一个广播流,否则在你收听之前没有事件),或者,如果有之前没有活动,您需要 下一个 活动。

对于普通的 Dart Stream,这是不可能的。它不记得以前的事件。您需要之前收听过该流,以便了解最近的事件是什么(但如果您这样做,它就不一定是广播流)。

您可以相当轻松地构建自己的记忆流包装器(但与异步编程一样,您需要注意竞争条件)

// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
import "dart:async";

/// Listens to [source] to returned stream.
///
/// Each listener on the returned stream receives the most recent
/// event sent on [source] followed by all further events of [source]
/// until they stop listening.
/// If there has been no events on [source] yet, only the further events
/// are forwarded.
Stream<T> mostRecentStream<T>(Stream<T> source) {
  var isDone = false;
  var hasEvent = false;
  T? mostRecentEvent;
  List<MultiStreamController>? pendingListeners;
  var listeners = <MultiStreamController>[];

  void forEachListener(void Function(MultiStreamController) action) {
    var active = 0;
    var originalLength = listeners.length;
    for (var i = 0; i < listeners.length; i++) {
      var controller = listeners[i];
      if (controller.hasListener) {
        listeners[active++] = controller;
        if (i < originalLength) action(controller);
      }   
    }
    listeners.length = active;
  }

  source.listen((event) {
    mostRecentEvent = event;
    hasEvent = true;
    forEachListener((controller) {
      controller.addSync(event);
    });
  }, onError: (e, s) {
    forEachListener((controller) { 
      controller.addErrorSync(e, s);
    });
  }, onDone: () {
    isDone = true;
    for (var controller in listeners) {
      controller.close();
    }
    listeners.clear();
  });

  return Stream<T>.multi((controller) {
    if (hasEvent) controller.add(mostRecentEvent as T);
    if (isDone) {
      controller.close();
    } else {
      listeners.add(controller);
    }  
  });
}

有了它,您可以简单地执行 var recentStream = mostRecentStream(yourStream),然后再执行 recentStream.first 来获取最近的事件,或者,如果有 none,则下一个事件(如果有是一个,如果流完全为空,则会出现错误。