等待所有 Scala Futures 完成

Awaiting all Scala Futures to complete

我使用支持并发操作的图像库有这样的理解 https://github.com/sksamuel/scrimage :

for (
      file <- myDirectory.listFiles;
      image <- AsyncImage(file);
      scaled <- image.scale(0.5)
      // possibly more ops here? 
    )
    {
      scaled.writer(Format.PNG).write(new File(dirOutput + file.getName))
    }

这里是 write() 的定义:

def write(out: OutputStream)(implicit executionContext: ExecutionContext): Future[Unit] = Future {
  writer.write(out)
}

我想做的是等到我的目录中的所有图像都完成大小调整后,我的程序才会关闭。从我从 SO 上的其他帖子中收集到的内容来看,基本上是将所有这些 Futures 填充到 Futures 列表中,然后使用 Await 来完成......有人可以帮我吗?

您遇到的问题是您混合了两种不同的单子理解,即 listFiles returns a List[File]image.scale returns a Future[Image]。虽然两者都可以在 for-comprehension 中使用,但不能混合使用。此外,image <- AsyncImage(file) 应该是一个赋值,因为它只是 returns 一个实例:

// start the scaling operations (this is a List comprehension)
val scaleOps: List[Future[Unit]] = for {
  file <- myDirectory.listFiles
  image = AsyncImage(file)

  // Now transform the image into a Future[Unit] with a nested Future comprehension
  ops = for {
    scaled <- image.scale(0.5)
    written <- scaled.writer(Format.PNG).write(new File(dirOutput + file.getName)) 
  } yield { written }
} yield { ops }

// collect and await the results
Await.result(Future.sequence(scaleOps), 10 minutes)

在外部理解中 <- 总是从 Listyield returns 最终列表中生成一个项目。

在内部理解中 <- 始终生成 Future 的值,允许您将其用作另一个生成 Future 的调用的输入,从而生成 Future[Unit] 来自 image.