0

对不起,但我是 Scala 的新手。我已经阅读了有关 Futures 和 Akka 的信息,但是我仍然在为我的方法返回字符串时遇到问题。

我有一个方法 getAuthString 应该返回身份验证字符串(或令牌)。我使用了喷雾 Jsonsupport,我可以打印结果

def getToken(url: String, username: String , password: String) = Future[String]{

import MyJsonProtocol._
import spray.httpx.SprayJsonSupport._

val pipeline: HttpRequest => Future[AuthTokenResult[Entry]] = (addCredentials(BasicHttpCredentials(username, password))
  ~> sendReceive
  ~> unmarshal[AuthTokenResult[Entry]]
  )
val myfutureResponse: Future[AuthTokenResult[Entry]] = pipeline(Get(url))

myfutureResponse onComplete {
      case Success(AuthTokenResult(Entry(Content(authString)):: _)) => println(authString)
      case Failure(error) => println("An error has occured: " + error.getMessage)
    }

这将解组 json 并打印所需的 authString。但是,印刷对我没有好处。我知道 onComplete 返回单位。我想返回 authString 以便我可以在其他地方使用它来处理另一个请求。我想我将不得不使用平面地图或地图,但我不确定如何。我需要我的方法来返回 authString 或错误。

4

1 回答 1

1

你不想返回 a String,你想返回 a Future[String]- 一旦某些东西是异步的,使它不异步的唯一方法是阻塞,这(通常)是一种浪费,使整个异步性毫无意义。

我不确定您为什么要将整个事情都包装在Future其中 - 琐碎的计算可以自己发生,将它们强制到单独的线程上几乎没有价值。所以你想要这样的东西:

def getToken(url: String, ...): Future[String] = {
  ...
  val myFutureResponse: Future[AuthTokenResult[Entry]] = ...
  myFutureResponse map {
    case AuthTokenResult(Entry(Content(authString))::_) => authString
  }
}

因此,您可以通过计算map将 aFuture转换为另一个Future。这将“通过”错误,但您可以使用类似的东西,recover或者recoverWith如果您想以特定方式处理它们。

然后,当您想Future[String]在 Spray 路线中使用 your 时,可以使用onSuccessoronComplete指令:

val myRoute = (path("/somewhere") & parameter("authData") {
  authData =>
    onSuccess(getToken(authData)) {
      authToken =>
        complete("Authed as " + authToken)
    }
  }

这将以Future适当的异步、反应方式使用,而不会阻塞。

于 2014-11-09T11:54:51.070 回答