斯卡拉 - 期货和期货 [英] Scala - Futures and Eithers

查看:206
本文介绍了斯卡拉 - 期货和期货的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个线程给了我一个如何构造我的代码的想法: Scala方式处理理解条件?

this thread gave me an idea how to structure my code: Scala-way to handle conditions in for-comprehensions?

有关部分:

// First create the JSON
val resultFuture: Future[Either[Failure, JsResult]] = for {
  userRes <- userDao.findUser(userId)
  user    <- userRes.withFailure(UserNotFound).right
  authRes <- userDao.authenticate(user)
  auth    <- authRes.withFailure(NotAuthenticated).right
  goodRes <- goodDao.findGood(goodId)
  good    <- goodRes.withFailure(GoodNotFound).right
  checkedGood <- checkGood(user, good).right
} yield renderJson(Map("success" -> true)))

这是我不明白的那一行:

This are the lines I do not understand:

user    <- userRes.withFailure(UserNotFound).right
authRes <- userDao.authenticate(user)

userRes.withFailure(UserNotFound).right 映射到 userDao.authenticate(user)。这将会创造一个新的右侧的未来,正确吗?

The userRes.withFailure(UserNotFound).right is mapped to userDao.authenticate(user). This will create a new Either with a Future on its right, correct?

如何

val resultFuture: Future[Either[Failure, JsResult]]

类型。我想,而不是JsResult,应该有另一个未来。
任何人都可以解释这一点吗?

be of its type. I think instead of a JsResult there should be another future. Can anyone explain this to me?

编辑:由于cmbaxter和Arne Claassen证实了这一点,新问题是:我该怎么写这段代码,所以看起来不丑,但干净,结构化?

EDIT: Since cmbaxter and Arne Claassen confirmed this, the new question is: How should I write this code, so it does not look ugly, but clean and structured?

推荐答案

相信您收到的答案不必要地混合未来已经完全能够通信失败时, 。你失踪的主要事情是一种从 Option 获取该选项的值而不显式抛出异常的方法。

I believe the answer you received needlessly mixed Either's into the mix when Future's are already perfectly capable of communicating failure. The main thing you were missing was a way to get from an Option to the option's value without explicitly throwing exceptions.

我建议您将Failures对象更改为以下内容:

I would suggest that you change the Failures object to the following:

object Failures {

  sealed trait Failure extends Exception

  // Four types of possible failures here
  case object UserNotFound extends Failure

  case object NotAuthenticated extends Failure

  case object GoodNotFound extends Failure

  case object NoOwnership extends Failure

  // Put other errors here...

  // Converts options into Futures
  implicit class opt2future[A](opt: Option[A]) {
    def withFailure(f: Failure) = opt match {
      case None => Future.failed(f)
      case Some(x) => Future.successful(x)
    }
  }
}

现在,您可以将 Future [Option [A]] 映射到 Future [A] 并指定故障条件,导致这样的理解:

Now you can map a Future[Option[A]] to a Future[A] and specify the failure condition, resulting in a for comprehension like this:

def checkGood(user: User, good: Good) =
  if (checkOwnership(user, good))
    Future.successful(good)
  else
    Future.failed(NoOwnership)

val resultFuture: Future[JsResult] = for {
  userOpt <- userDao.findUser(userId)
  user <- userOpt.withFailure(UserNotFound)
  authOpt <- userDao.authenticate(user)
  auth <- authOpt.withFailure(NotAuthenticated)
  goodOpt <- goodRes.withFailure(GoodNotFound)
  checkedGood <- checkGood(user, good)
} yield renderJson(Map("success" -> true))))

现在你有一个 Future [JsResult] / code>可以将失败的场景映射到所需的输出和成功场景只是JsResult。希望你在一个异步框架中使用这个框架,它希望你能为自己提供一个未来,并且有自己的失败的未来的错误响应映射(如Play!)。

Now that you have a Future[JsResult] you can map the failed scenarios to your desired output and the success scenario is just the JsResult. Hopefully you are using this in an asynchronous framework which expects you to feed it a future and has its own failed future to error response mapping (such as Play!).

这篇关于斯卡拉 - 期货和期货的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆