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