我使用http4s 0.15.16a和光滑的3.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 ....
}
答案 0 :(得分:1)
您可以将一个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)
}
结果将是[{1}}和Future
的常见超类型的jsonOK
(不熟悉您正在使用的库;所以我可能有类型加载错误:它不是InternalServerError
吗?)。
BTW:您的原始代码有一个非常有问题的一行:
Future[Try[_]]
val ll = res.value.get.get
是res.value
。在Option[Try[T]]
或get
上拨打Option
通常是一个坏主意(即使在这种情况下由于Try
,Await
也不应该{ {1}},因此Option
在技术上是安全的)因为它可以抛出异常。您最好使用None
,get
和朋友。
答案 1 :(得分:0)
问题是http4s 0.15使用Scalaz并发结构,而Slick使用本机Scala,而这两者并不是为了相互协作而设计的。我的理解是http4s 0.17+已经从Scalaz切换到Cats,这可能需要使用本机Scala Futures,所以如果你可以升级那么可能值得一试。如果没有,您可以通过手动创建包装未来的任务来处理转换:
def scalaFutureRes = MySlickDAO.load(id)
val scalazTaskRes = Task.async { register =>
scalaFutureRes.onComplete {
case Success(success) => register(success.right)
case Failure(ex) => register(ex.left)
}
}
此时你已经从Future [ResultType]获得了一个Task [ResultType],您可以使用其余的逻辑映射/ flatMap,就像Levi的答案一样。
您还可以使用delorean库来实现此逻辑,并通过隐式转换在相关类上定义相反的方向,这样您就可以在Future上调用.toTask来获取它兼容的形式。他们的自述文件也有很多关于转换的有用信息以及存在的缺陷。