2014-11-09 63 views
0

对不起,但我是斯卡拉新手。我已阅读关于期货和阿卡,但我仍然有问题返回一个字符串为我的方法。喷客户端我想从Json响应中返回字符串

我有一个方法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或错误。

回答

1

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

我不确定你为什么要把所有的东西都包装在Future之中 - 计算中的一小部分可以单独发生,但是把它们强制到一个单独的线程中几乎没有什么价值。所以,你想是这样的:

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

所以你使用mapFuture转换为另一个Future与计算。这会“传递”错误,但如果您想以特定方式处理它们,则可以使用类似recoverrecoverWith的内容。

然后,当你想用你的Future[String]在喷雾途径,你可以使用onSuccessonComplete指令:

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

这将在适当的异步,被动的方式使用Future,而不会阻塞。

+0

感谢@Imm为您的及时响应。你给了我足够的指示,我很满意你的回复,但请原谅我的无知。如果我使用路由方法,那意味着我需要进行API调用的所有代码**/url/path +?authToken **必须位于单个代码块中。为什么我不能使用像** Val mytoken = getToken(url,...)**这样的东西,这样每次我需要创建一个API请求时,我都可以将token附加到我的url中,作为我的请求参数的一部分。你说这将被阻止如果我这样做,问题是我最终会没有可重复使用的代码 – Sheggetin 2014-11-09 18:45:19

+0

哦,我没有意识到你只是使用喷雾客户端。你可以使用Promise来保存'authToken':'val authToken = Promise [String](); authToken.completeWith(getToken())',然后在其他代码中使用'authToken.future'。或者你可以使用演员。或者,也许你的代码不需要异步,在这种情况下,你可以'val authToken = Await.result(getToken(),30秒)'。在这种情况下,最好不要使用喷雾 - 它增加了高性能并行代码所需的复杂性,但简单的情况下可以使用更简单的库。 – lmm 2014-11-09 19:29:18