我有一个函数必须返回一个 Future[Unit]。
在我的函数中,我正在编写一个返回 Future[IOResult] 的文件。未来和 IOResult 都可能具有故障状态。
我想在我的函数中检查未来和 IOResult 的成功和失败,但只需从此函数返回一个故障[单元],这可能吗?
下面的代码报告错误:
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)
}
}
三件事。
-
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
}
这可能有效:
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
将展平match
语句返回的嵌套Future
,recover
现在返回Unit
以便结果Future[Unit]
。recover
将捕获生成的所有错误,因此您无需在内部Failure
的情况下打印任何内容。
您返回的是 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 { _ => () }