2014-11-09 9 views
0

죄송합니다. 그러나 Scala를 처음 사용했습니다. Futures와 Akka에 대해 읽었지 만, 여전히 메서드에 문자열을 반환하는 데 문제가 있습니다.스프레이 클라이언트 Json 응답에서 String을 반환하고 싶습니다.

인증 문자열 (또는 토큰)을 반환해야하는 getAuthString 메서드가 있습니다. 나는 스프레이 Jsonsupport을 사용하고 난이이 JSON을 비 정렬 화 결과

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) 
    } 

를 인쇄하고 원하는 authString를 인쇄 할 수 있습니다. 그러나 인쇄는 나에게 좋지 않습니다. 나는 onComplete 리턴 유닛을 안다. 다른 요청으로 다른 곳에서 사용할 수 있도록 authString을 반환하고 싶습니다. 플랫 맵이나 맵을 사용해야 할 것 같지만 어떻게 확신 할 수없는 것입니다. authString 또는 오류를 반환하는 내 메서드가 필요합니다.

답변

1

String을 반환하고 싶지 않으신 경우 Future[String]을 반환하고 싶습니다. 일단 비동기가 아닌 것이 비동기가 아닌 것을 차단하는 유일한 방법은 차단하는 것이며, 이는 일반적으로 낭비이므로 전체 async- 끝장이 없다.

나는 왜 Future에 모든 것을 포함하고 있는지 알지 못합니다. 계산의 작은 부분은 독자적으로 발생할 수 있습니다. 별도의 스레드에 강제로 적용하는 데는 가치가 없습니다.

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

그래서 당신이 계산과 다른 FutureFuture를 변환하는 map를 사용 : 그래서 당신이 뭔가를 할 수 있습니다. 이것은 "통과"오류가 발생하지만 특정 방식으로 처리하려는 경우 recover 또는 recoverWith과 같은 것을 사용할 수 있습니다.

그런 다음 당신은 당신이 onSuccess 또는 onComplete 지시어를 사용할 수 있습니다, 스프레이 경로에 Future[String]를 사용하고자 할 때 : 이것은 차단하지 않고, 적절한 비동기, 반응 방식으로 Future를 사용합니다

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

.

+0

귀하의 신속한 답변을 위해 감사합니다. 당신은 나에게 충분한 조언을 주었고 나는 당신의 대답에 행복해하지만, 나의 무지를 용서해 주었다. 라우팅 방식을 사용하면 API 호출 **/url/path +? authToken **을 작성해야하는 모든 코드가 단일 코드 블록에 있어야합니다. ** Val mytoken = getToken (url, ...) **과 같은 것을 사용할 수 없기 때문에 API 요청을 할 때마다 요청 매개 변수의 일부로 내 URL에 토큰을 추가 할 수 있습니다. . 당신은 이것이 차단 될 것이라고 말했다. 내가 그랬다면, 문제는 내가 재사용 가능한 코드없이 끝날 것이라는 것이다. – Sheggetin

+0

오, 나는 스프레이 클라이언트를 사용하고 있다는 것을 깨닫지 못했다. Promise를 사용하여'authToken'을 보관할 수 있습니다 : val authToken = Promise [String](); authToken.completeWith (getToken())'그런 다음 다른 코드에서'authToken.future'를 사용합니다. 또는 배우를 사용할 수도 있습니다. 또는 어쨌든 코드가 비동기 일 필요는 없습니다.이 경우에는'val authToken = Await.result (getToken(), 30 seconds)'만 할 수 있습니다. 이 경우 스프레이를 전혀 사용하지 않는 것이 더 좋을 수도 있습니다. 고성능 병렬 코드에 필요한 복잡성이 추가되지만 단순한 경우에는 더 간단한 라이브러리를 사용할 수 있습니다. – lmm