如何使用StreamChannel在Dart中进行双向通信?

时间:2018-04-24 16:05:44

标签: stream dart

有没有办法让Dart Streams做类似的事情 连续多次await stream.first,使用有点像堆栈/队列的流?

据我了解,你可以在现有的Single-substription流上使用asBroadcastStream来做到这一点,但我觉得这并不理想。

也许有一种缓冲原语带有一些Rx包或类似的东西?

我的用例如下:

我有StreamChannelIOWebSocketChannel),我想按特定顺序发送/接收消息。

即:

Send Message0
Receive Message1
Send Message2
Receive Message3

我确信Message1只会在服务器收到Message0后到达 (等Message2Message3

1 个答案:

答案 0 :(得分:7)

对于基于推送的事件基于拉取的资源读取,Dart具有单一抽象的优势(在我看来,不利)。这导致了许多其他混淆,例如"Do I have to cancel stream subscriptions"

在基于推送的模型中,请说:

abstract class Element {
  Stream<MouseEvent> get onClick;
}

当发生点击时,该类通知。可能存在介于0和字面无限点击事件之间的任何位置,并且通常不希望以与读取资源相同的方式缓冲或处理它们(特别是考虑到Dart是单线程的)。 另一个注意事项此流的任何订阅者数量是完全有效的(多个类可能有兴趣知道点击何时发生)。

另一方面,有一个基于拉的模型,比如读取文件:

abstract class File {
  Stream<String> readLines();
}

这个的情况下,您可能希望逐行处理,甚至可能在您点击某个字符串后停止,并且肯定希望通过EOF(通常由“完成”事件,或流闭幕,在惯用的Dart中)。 另一个注意事项:拥有超过1个订阅者的有效 - 这会很快变得棘手。

对于您的特定问题,您似乎想:

  • 发送您自己的活动
  • 按需接收下一个事件
  • 处理活动,发送您自己的活动
  • 等...

好的,让我们来看看你问题的具体细节:

  

据我了解,你可以在现有的Single-substription流上使用asBroadcastStream来做到这一点,但我觉得这并不理想。

非常不理想。单订阅流(我称之为“资源流”,如上面的readLines调用)自动缓冲事件并等待订阅者。 接收一行文本是非常糟糕的,因为在文件被读取之后订阅发生了

另一方面,广播流缓冲事件。因此,如果您根据时间安排等问题采用您的方法,您可能会发现自己正在丢失事件。

这里有几个选项。没有一个是完美的,但他们可能会有所帮助:

  • package:stream_transform包有一组Stream常用的转换,包括一些受RX启发的转换。

  • package:async包具有其他用于处理异步代码的实用程序。具体来说,您可能会发现StreamQueue完全符合您的要求:

    Future<void> processEvents(Stream<String> inputStream) async {
      var queue = new StreamQueue(inputStream);
      while (await queue.hasNext) {
        var next = await queue.next;
        // Insert processing here.
      }
    }
    

我发现自己希望StreamQueue dart:async中是,并且用于资源和流的Stream之间没有共享接口用于事件,但今天这是一个不错的方法。

干杯!