当前位置: 首页 > 知识库问答 >
问题:

scala func中处理选项未来的干净方法

左博学
2023-03-14

我有一些简单的枚举名:失败/成功的结果

sealed trait Result

case object Success extends Result

case object Fail extends Result

我有一个函数,它什么也没有得到,但返回未来的结果,

def do(): Future[Result] = {

    someService.getInfo() flatMap { responseInfo =>
      responseInfo.fold(Future.successful[Result](Result)) { info =>
       myDB.getData(info.resId) map { dbRes =>
            if (dbRes.isSomething) Fail else Success
        } recover {
           case e: NotFoundException => Fail
         }
      }
    }
}

我不喜欢我的解决方案,它看起来很凌乱,有更简单的吗?

someService.getInfo返回未来[选项[响应信息]]

我想在这里做的是,如果一些Service.getInfo返回None,那么func应该返回Future[Fail],否则调用db,这也返回一个case类的未来,并基于响应返回Fail/Success。

但我正在寻找一种超级时尚的斯卡拉方式,让它看起来不错:)

谢谢

共有1个答案

夹谷俊远
2023-03-14

您正在创建成功失败的新概念,scala.concurrent.Future已经有了,所以您正在做的事情毫无意义。

你有你想要的所有失败状态表示,因为在一个< code>Future里面隐藏了一个< code>scala.util.Try,所以你已经可以< code>match,< code>fold等等,任何其他正常的流控制方法都在那里。

def do(): Future[Option[DbResult]] = {

    someService.getInfo() flatMap { responseInfo =>
      responseInfo.fold(Future.successful(_)) { info =>
       myDB.getData(info.resId) map { dbRes =>
            if (dbRes.isSomething) Some(dbRes) else None
        } recover {
           case e: NotFoundException => Future.failed(e)
        }
      }
    }
}

将概念混为一谈也不是一个好主意。例如,在给定查询的数据库中“找不到”结果是一种非常有效的状态,它与你失败的未来无关。

将来的失败应该代表网络故障、格式错误的查询等,而不是数据库正确返回没有结果的有效往返。因此,您可以使用Option

莫纳德变压器

这是一个将< code>G[F[_]]转换为< code>F[G[_]]的一般性问题,其中需要处理包装类型的有趣组合。说出< code >期货[期权[T]]到< code >期权[期货[T]]。处理这种东西的函数式方法有点麻烦,但是值得。

import cats.data.OptionT
import cats.std.future._

def do() = {
  val chain = for {
    info <- OptionT(someService.getInfo())
    data <- OptionT(myDB.getData(info.resId) map { dbRes =>
            if (dbRes.isSomething) Some(dbRes) else None
        } recover {
           case e: NotFoundException => Future.failed(e)
        })
  } yield data

  chain.value
}

它看起来与上面相似。在此处阅读有关OptionT的更多信息,但它看起来像您想要的。

 类似资料:
  • 问题内容: 我有一个带有参数的方法,该参数可以为NULL。我想将输入的本地副本作为结束。现在,我的代码如下所示: 有没有更清洁的方法可以做到这一点?如果是一个简单的参数,我可以做类似的事情,但是我不确定是否有类似处理集合的事情。 问题答案: 我不明白为什么您不能使用: 您可以使用静态导入保存某些类型的输入,如果您要这样做的话:

  • 问题内容: 我正在学习RxJava,并且在很多地方看到可以通过这种方式处理错误: 我是唯一认为这确实是错误代码的人吗?我该如何做得更好?我虽然使用了“访问”我的基本异常的每种具体类型的模式,但是方法始终需要一个;。您不能使用自己的基本异常。 问题答案: 错误处理程序: 您可以这样使用:

  • 问题内容: 一个没有stopServer功能的RMI服务器,可以正常工作。 每当被调用异常中的stopServer()抛出时 这是堆栈跟踪 即使我使用清理服务对象,情况也一样 有人可以提出一种干净的方法来停止服务器,这还会释放端口以供重用。 问题答案: 您需要存储结果并取消导出结果。目前,您正在尝试取消导出存根。

  • 我有两个函数返回期货。我正试图使用for-yield理解将第一个函数的修改结果输入到另一个函数中。 此方法有效: 然而,我对“如果”在那里不满意,似乎我应该能够使用地图。 但是当我尝试使用地图时: 我得到一个编译错误: 我尝试了一些变化,但没有发现任何有吸引力的工作。有人能提出更好的理解和/或解释我的第二个例子的错误吗? 下面是一个最小但完整的Scala 2.10可运行示例:

  • 问题内容: 有时候减速器会变得凌乱: 还有更简洁的方法吗? 问题答案: UPD :现在已成为ES2018的一部分 可以通过 非标准化 但属性扩展的语法来稍微改善它:

  • 问题内容: 顾名思义,是否有适当的方法来设置一些初始CSS属性(或类),并告诉浏览器将其转换为另一个值? 这不会激活Chrome 29 / Firefox 23中元素的不透明度。这是因为(源): […]您会发现,如果同时应用两组属性,则立即应用一组属性,然后浏览器将尝试优化属性更改,而忽略您的初始属性并防止过渡。在幕后,浏览器在绘画之前先批处理属性更改,这通常会加快渲染速度,但有时可能会产生不利影