微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决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 举报,一经查实,本站将立刻删除。