Scala FS2:是否可以优雅地完成队列?

Scala FS2:是否可以优雅地完成队列?,scala,fs2,Scala,Fs2,假设我想将一些遗留异步API转换为FS2流。 API提供了一个包含3个回调的接口:next元素、success和error。 我希望流发出所有元素,然后在收到成功或错误回调后完成 FS2指南()建议在这种情况下使用FS2.Queue, 它对于排队非常有效,但是到目前为止我看到的所有示例都期望queue.dequeue返回的流永远不会完成- 在我的情况下,没有明显的方法来处理成功/错误回调。 我尝试使用queue.dequeue.interruptWhen(…信号来了…),但是如果成功/错误回调在

假设我想将一些遗留异步API转换为FS2流。 API提供了一个包含3个回调的接口:next元素、success和error。 我希望流发出所有元素,然后在收到成功或错误回调后完成

FS2指南()建议在这种情况下使用
FS2.Queue
, 它对于排队非常有效,但是到目前为止我看到的所有示例都期望
queue.dequeue
返回的流永远不会完成- 在我的情况下,没有明显的方法来处理成功/错误回调。 我尝试使用
queue.dequeue.interruptWhen(…信号来了…
),但是如果成功/错误回调在客户端从流中读取数据之前到达, 流被提前终止-仍有未读元素。我希望消费者在完成流之前完成阅读

FS2有可能做到这一点吗?对于Akka Streams,它很简单-
SourceQueueWithComplete
complete
fail
方法

更新: 通过将元素包装在Option中并将“无”视为停止读取流的信号,以及通过使用传播错误的承诺,我能够获得足够好的结果:

queue.dequeue
.interruptWhen(interruptingPromise.get)
.takeWhile(_.isDefined).map(_.get)

然而,我是否忽略了做这些事情的更自然的方法?

一种惯用的方法是创建一个
队列[Option[a]]
,而不是
队列[a]
。排队时,使用
Some
,您可以显式地将
None
排队以表示完成。在出列端,执行
q.dequeue.unNoneTerminate
,这将为您提供一个
流[F,a]
,该流在队列发出
None
时终止。回答您的更新:将
unNoneTerminate
rethrow
组合,它接受
流[F,或者[Throwable,a]
,并返回
流[F,a]
当遇到可丢弃文件时,会与
Stream.raiseError一起出错

然后,您的整个堆栈将成为一个
流[F,或者[Throwable,Option[a]]]
,您可以通过调用
.rethrow.unNoneTerminate
将其展开为
流[F,a]