我有一个必须返回Future [Unit]的函数。
在我的函数中,我正在编写一个返回Future [IOResult]的文件。 Future和IOResult都可以具有故障状态。
我想在我的函数中检查Future和IOResult的成功和失败,但是仅从此函数返回Failure [Unit],这可能吗?
下面的代码报告错误:
discarded non-Unit value
[error] Future.successful(Unit)
discarded non-Unit value
[error] Future.failed(e)
这是我的功能:
def create(filePath: String, fileStream: Source[ByteString, Any]): Future[Unit] = {
val writeResultFuture: Future[IOResult] = fileStream.runWith(FileIO.toPath(filePath))
writeResultFuture map { writeResult =>
writeResult.status match {
case Success(_) =>
logger.info(s"Successfully uploaded: ${fileInfo.fileName} to: $filePath")
Future.successful(Unit)
case Failure(e) =>
logger.error(s"Failed to upload: ${fileInfo.fileName} to: $filePath", e)
Future.failed(e)
}
} recover {
case e =>
logger.error(s"Failed to upload: ${fileInfo.fileName} to: $filePath", e)
Future.failed(e)
}
}
答案 0 :(得分:4)
三件事。
Unit
不是类型Unit
的值(它是对Scala库中定义的object scala.Unit
的引用)。您希望()
表示值Unit
。
您赋予recover
的函数应该返回实际结果,而不是Future
(recoverWith
适用于期货)。
您赋予map
的函数也返回实际结果。如果您确实需要返回flatMap
Future
所以,这样的事情应该起作用:
writeResultFuture.map { writeResult =>
writeResult.status match {
case Success(_) =>
logger.info(s"Successfully uploaded: ${fileInfo.fileName} to: $filePath")
case Failure(e) =>
logger.error(s"Failed to upload: ${fileInfo.fileName} to: $filePath", e)
throw e
}
}.recover { case e =>
logger.error(s"Failed to upload: ${fileInfo.fileName} to: $filePath", e)
throw e
}
更好的是,使用onFailure
而不是recover
-这样就无需重新投掷。只需.onFailure { e => logger.error(...) }
另外,请注意,您以这种方式记录了两次错误(一次在map
内,然后再次在recover
/ onFailure
中)…考虑一起删除recover
部分。
writeResultFuture.map(_.status).map {
case Success(_) => logger.info(s"Successfully uploaded: ${fileInfo.fileName} to: $filePath")
case Failure(e) => logger.error(s"Failed to upload: ${fileInfo.fileName} to: $filePath", e)
throw e
}
答案 1 :(得分:0)
这可能有效:
writeResultFuture flatMap { writeResult =>
writeResult.status match {
case Success(_) =>
logger.info(s"Successfully uploaded: ${fileInfo.fileName} to: $filePath")
Future.successful()
case Failure(e) =>
Future.failed(e)
}
} recover {
case e =>
logger.error(s"Failed to upload: ${fileInfo.fileName} to: $filePath", e)
}
使用flatMap
将使Future
语句返回的嵌套match
变平,并且recover
现在返回Unit
,因此结果为Future[Unit]
。 recover
将捕获所有生成的错误,因此您无需在内部Failure
情况下打印任何内容。
答案 2 :(得分:0)
您要返回Future,因此您的最终结果将为Future [Future […]]类型,在您的情况下,我们根本不需要嵌套,因此可以将代码更改为:
免责声明:我只在这里输入了代码,尚未进行类型检查,YMMV。没有保证。等等
fileStream.runWith(FileIO.toPath(filePath)) transform {
case Failure(e) => Failure(e)
case Success(i: IOResult) => i.status
} andThen {
case Success(_) =>
logger.info(s"Successfully uploaded: ${fileInfo.fileName} to: $filePath")
case Failure(e) =>
logger.error(s"Failed to upload: ${fileInfo.fileName} to: $filePath", e)
}
} map { _ => () }