我是异步编程的新手。我读了这篇教程http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html,惊讶于我可以如此毫不费力地将Future整合到程序中。然而,当我在路由中使用Future时,返回类型是错误的。
get {
optionalCookie("commToken") {
case Some(commCookie) =>
val response = (MTurkerProgressActor ? Register).mapTo[..].map({...})
val result = Await.result(response, 5 seconds)
setCookie(HttpCookie("commToken", content = result._2.mturker.get.commToken)) {
complete(result._1, result._2.mturker.get)
}
case None => // ...
}
}我真的不想使用Await (如果我只是阻塞线程并等待5秒,那么异步有什么意义呢?)我尝试使用for-comprehension或flatMap,并将setCookie和complete操作放在其中,但返回类型是不可接受的。For-comprehension返回“单位”,flatMap返回未来。
因为我需要设置这个cookie,所以我需要里面的数据。Await是解决方案吗?或者有没有什么办法?
发布于 2014-07-14 20:52:32
您可以使用onSuccess指令:
get {
optionalCookie("commToken") { cookie =>
//....
val response = (MTurkerProgressActor ? Register).mapTo[..].map({...})
onSuccess(response) {
case (result, mTurkerResponse) =>
setCookie(HttpCookie("commToken", content = mTurkerResponse.mturker.get.commToken)) {
complete(result, mturkerResponse.mturker.get)
}
}
}还有onFailure和onComplete (对于它们,您必须在Success和Failure上匹配),请参阅http://spray.io/documentation/1.2.1/spray-routing/future-directives/onComplete/
而且,与直接使用get相比,使用map (我假设mturker是一个Option或类似的东西)要方便得多:
case (result, mTurkerResponse) =>
mTurkerResponse.mturker.map { mt =>
setCookie(HttpCookie("commToken", content = mt.commToken)) {
complete(result, mt)
}
}发布于 2016-01-21 21:43:42
您还可以使用以下代码创建自定义指令-
case class ExceptionRejection(ex: Throwable) extends Rejection
protected def futureDirective[T](x: Future[T],
exceptionHandler: (Throwable) => Rejection = ExceptionRejection(_)) =
new Directive1[T] {
override def happly(f: (::[T, HNil]) => Route): Route = { ctx =>
x
.map(t => f(t :: HNil)(ctx))
.onFailure { case ex: Exception =>
ctx.reject(exceptionHandler(ex))
}
}
}示例用法-
protected def getLogin(account: Account) = futureDirective(
logins.findById(account.id)
)
getAccount(access_token) { account =>
getLogin(account) { login =>
// ...
}
}https://stackoverflow.com/questions/24726330
复制相似问题