简体   繁体   English

队列中的 fs2 Stream 不消耗元素

[英]fs2 Stream from queue doesn't consume elements

I want to create the stream from the queue that will print all the elements into the console.我想从将所有元素打印到控制台的队列中创建 stream。 The current one snippet doesn't print anything:当前的一个片段不打印任何内容:

object TestApp extends App {

  implicit val contextShift: ContextShift[IO] = IO.contextShift(ExecutionContext.global)

  private val value: IO[(fs2.Stream[IO, Unit], String => IO[Unit], () => IO[Unit])] = for {
    queue <- Queue.noneTerminated[IO, String]
  } yield {
    val stream: fs2.Stream[IO, Unit] = queue.dequeue.map(println)

    def send(msg: String): IO[Unit] = queue.enqueue1(Some(msg))

    def close(): IO[Unit] = queue.enqueue1(None)

    (stream, send _, close _)
  }

  val (stream, send, close) = value.unsafeRunSync()

  send("msg1").unsafeRunSync()
  send("msg2").unsafeRunSync()

}

what is wrong with stream creation? stream 创建有什么问题?

In your example, you're merely creating a queue and creating a description of the stream.在您的示例中,您只是创建了一个队列并创建了 stream 的描述。 In order to run the stream, you need to call compile which will expose several methods, that would allow running and consuming values of the steam, like toList , fold or drain为了运行 stream,您需要调用compile这将公开几个方法,这将允许运行和使用 steam 的值,例如toListfolddrain

In your case you're not really interested in values, since you only want to print them, so you should use drain :在您的情况下,您对值并不真正感兴趣,因为您只想打印它们,所以您应该使用drain

implicit val contextShift: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
implicit val timer: Timer[IO] = IO.timer(ExecutionContext.global)

private val value: IO[(fs2.Stream[IO, Unit], String => IO[Unit], () => IO[Unit])] = for {
  queue <- Queue.noneTerminated[IO, String]
} yield {
  //I changed map to evalMap, since printing is effect and should be wrapped in IO
  val stream: fs2.Stream[IO, Unit] = queue.dequeue.evalMap(v => IO(println(v)))

  def send(msg: String): IO[Unit] = queue.enqueue1(Some(msg))

  def close(): IO[Unit] = queue.enqueue1(None)

  (stream, send _, close _)
}

val (stream, send, close) = value.unsafeRunSync()

send("msg1").unsafeRunSync()
send("msg2").unsafeRunSync()
//Closing of stream will be delayed by 5s and run in separate fiber
close().delayBy(5.seconds).start.unsafeRunSync()

//steam would block here until it's closed
stream.compile.drain.unsafeRunSync()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM