如何解决Dart - 获取流的最后一个或第一个值
我有一个流,我需要使用这个流的最后一个值,如果这个流没有发出值,我需要等待第一个值。我只想使用这个值一次。正确的做法是什么?
解决方法
听起来您想要最近事件由流发出(这可能是广播流,因为否则在您侦听之前没有事件),或者,如果之前没有事件,您需要 next 事件。
对于普通的 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
以获取最近的事件,或者,如果没有,则获取下一个事件(如果有,您会得到一个如果流完全为空,则会出错)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。