2013-09-29 22 views
5

Piszę metodę kontrolera w strukturze gry, która wywołuje funkcję zwracającą przyszłość, która może również spowodować wyjątek. Mam problem z ustaleniem, jak złapać i obsłużyć ten wyjątek.Jak radzić sobie z wyjątkiem, który zdarza się w przyszłości w scala

Oto, co starałem:

def openIDCallback = Action { implicit request => 
    Async (
     Try(OpenID.verifiedId) match { 
     case Failure(thrown) => { 
      PurePromise(Ok("failed: " + thrown)) 
     } 
     case Success(successResult) => { 
      successResult.map(userInfo => { 
      Ok(userInfo.id + "\n" + userInfo.attributes) 
      }) 
     } 
     } 
    ) 
    } 

OpenID.verifiedId jest funkcja z Play OpenId API, która zwraca Przyszłość [UserInfo]. Poniżej źródło tych funkcji:

def verifiedId(queryString: Map[String, Seq[String]]): Future[UserInfo] = { 
    (queryString.get("openid.mode").flatMap(_.headOption), 
     queryString.get("openid.claimed_id").flatMap(_.headOption)) match { // The Claimed Identifier. "openid.claimed_id" and "openid.identity" SHALL be either both present or both absent. 
     case (Some("id_res"), Some(id)) => { 
     // MUST perform discovery on the claimedId to resolve the op_endpoint. 
     val server: Future[OpenIDServer] = discovery.discoverServer(id) 
     server.flatMap(directVerification(queryString))(internalContext) 
     } 
     case (Some("cancel"), _) => PurePromise(throw Errors.AUTH_CANCEL) 
     case _ => PurePromise(throw Errors.BAD_RESPONSE) 
    } 
    } 

Jak pokazano powyżej, działanie może powrócić PurePromise (rzut Errors.AUTH_CANCEL) i PurePromise (rzut Errors.BAD_RESPONSE). Moja próba rozwiązania obsługuje sukcesy poprawnie, ale na wyjątkami uzyskać:

play.api.Application$$anon$1: Execution exception[[AUTH_CANCEL$: null]] 

Moje pytanie brzmi jak mogę złapać i obsługiwać te wyjątki w mojej metody kontrolera?

Odpowiedz

10

Należy użyć recover metodę Future zamiast Try tak:

Async (
    OpenID.verifiedId. 
    map{userInfo => Ok(userInfo.id + "\n" + userInfo.attributes)}. 
    recover{ case thrown => Ok("failed: " + thrown) } 
) 

Try może pomóc w przypadku verifiedId zgłasza wyjątek zamiast wrócić Future. W twoim przypadku verifiedId pomyślnie zwraca Future (nawet jeśli będzie wyjątek w tym Future).

+0

Dzięki - zajrzałem do odzyskania, ale nie rozumiem pojęcia PartialFunction. Twój przykład zadziałał i wyjaśnił mi tę koncepcję. –

+0

@KresimirNesek: 'PartialFunction' (i dopasowywanie wzorców) jest jednym z najważniejszych i użytecznych narzędzi w scala. Zobacz '9. Sekcja dopasowywania wzoru w [informacja o tagach Scala] (http://stackoverflow.com/tags/scala/info). – senia