首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala映射Future[IOResult]到Future[Unit]

Scala映射Future[IOResult]到Future[Unit]
EN

Stack Overflow用户
提问于 2018-08-24 13:02:32
回答 3查看 1.6K关注 0票数 1

我有一个函数必须返回一个FutureUnit。

在我的函数中,我编写了一个返回FutureIOResult的文件。未来和IOResult都有失败的状态。

我想在我的函数中检查未来和IOResult的成功和失败,但是从这个函数返回一个FailureUnit,这可能吗?

下面的代码是报告错误:

代码语言:javascript
复制
discarded non-Unit value
[error]           Future.successful(Unit)

discarded non-Unit value
[error]           Future.failed(e)

这是我的功能:

代码语言:javascript
复制
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)
    }
  }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-24 14:01:07

三件事。

  1. Unit不是Unit类型的值(它是对scala库中定义的object scala.Unit的引用)。您希望()表示Unit的值。
  2. 您给recover的函数应该返回实际结果,而不是Future (recoverWith与期货一起工作)。
  3. 您给map的函数也返回实际结果。如果你真的需要返回一个flatMap,你会想要Future

所以,像这样的东西应该有效:

代码语言:javascript
复制
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部件。

代码语言:javascript
复制
  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
  }
票数 4
EN

Stack Overflow用户

发布于 2018-08-24 14:01:43

这样做可能会奏效:

代码语言:javascript
复制
  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语句返回的嵌套Futurerecover现在返回Unit,因此结果是Future[Unit]recover将捕获生成的所有错误,因此不需要在内部Failure大小写中打印任何内容。

票数 0
EN

Stack Overflow用户

发布于 2018-08-24 14:09:55

您正在返回未来的,所以您的最终结果将是类型未来[未来…],在您的情况下,我们根本不需要嵌套,因此我们可以将代码更改为:

免责声明:我只在这里输入了代码,它还没有被输入,YMMV。没有保证。等

代码语言:javascript
复制
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 { _ => () }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52005127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档