我有一个带有http4s 0.15.16a和slick3.2.1的scala项目,其中包括以下步骤:
问题是,我使用了一个Await.result,这是不好的实践,有更好的解决方案吗?
在这里,代码:
val service = HttpService {
//http://localhost:8080/rest/id/9008E75A-F112-396B-E050-A8C08D26075F
case GET -> Root / "rest" / "id" / id =>
val res = MySlickDAO.load(id)
Await.result(res, Duration.Inf)
val ll = res.value.get.get
ll match {
case Failure(x) =>
InternalServerError(x)
case Success(record) =>
val r = record.map(x => MyEntity(x._1, x._2, x._3))
jsonOK(r.asJson)
}
case ....}
发布于 2017-09-19 19:17:32
不必等待,您可以将一个Future的结果链接到另一个:
val resFut = MySlickDAO.load(id)
resFut.map { record =>
val r = record.map(x => MyEntity(x._1, x._2, x._3))
jsonOK(r.asJson)
} recover { x =>
InternalServerError(x)
}这样做的结果将是一个普通超级类型的Future和InternalServerError (不熟悉您正在使用的库;所以我可能有错误的加载类型:它不是Future[Try[_]],对吗?)
顺便说一句:您的原始代码有一个非常有问题的行:
val ll = res.value.get.getres.value是Option[Try[T]]。在Option或Try上调用Try通常是个坏主意(即使在这种情况下,由于Await,Option不应该是None,所以get在技术上是安全的),因为它会引发异常。您最好使用map、flatMap和朋友。
发布于 2017-11-17 16:19:00
问题是,http4s 0.15使用Scalaz并发结构,而Slick使用原生Scala结构,这两个结构不是设计用来相互工作的。我的理解是,http4s 0.17+已经从Scalaz转向Cats,这可能需要使用本地Scalaz,所以如果您可以升级,这可能值得一试。如果不是,您可以通过手动创建一个包装您的未来的任务来处理转换:
def scalaFutureRes = MySlickDAO.load(id)
val scalazTaskRes = Task.async { register =>
scalaFutureRes.onComplete {
case Success(success) => register(success.right)
case Failure(ex) => register(ex.left)
}
}此时,您已经得到了一个来自TaskResultType的FutureResultType,您可以映射/平面图与您的逻辑的其余部分,如在Levi的答案。
您还可以为此使用德洛伦库,它具有此逻辑,并且通过隐式转换在所讨论的类上定义了相反的方向,这样您就可以调用未来上的.toTask以兼容的形式获得它。他们的自述文件中也有很多关于转换和陷阱的有用信息。
https://stackoverflow.com/questions/46306703
复制相似问题