2013-09-29 8 views
5

Sto scrivendo un metodo di controllo nel framework di gioco che chiama una funzione che restituisce un Futuro che può anche generare un'eccezione. Ho difficoltà a capire come catturare e gestire quell'eccezione.Come gestire un'eccezione che si verifica in un futuro in scala

Ecco cosa ho provato:

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 è la funzione di riproduzione del OpenID api che restituisce Futuro [UserInfo]. Ecco la fonte di tale funzione:

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

Come indicato sopra, funzione può restituire PurePromise (gettare Errors.AUTH_CANCEL) e PurePromise (gettare Errors.BAD_RESPONSE). Il mio tentativo di soluzione gestisce successi correttamente, ma sulle eccezioni ottengo:

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

La mia domanda è come faccio a catturare e gestire queste eccezioni nel mio metodo di controllo?

risposta

10

Si dovrebbe usare recover metodo Future invece di Try come questo:

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

Try può aiutare in caso verifiedId genera un'eccezione invece di ritornare Future. Nel tuo caso verifiedId restituisce correttamente Future (anche se ci sarà un'eccezione in questo Future).

+0

Grazie - ho cercato di recuperare ma non ho capito il concetto di PartialFunction. Il tuo esempio ha funzionato e ha chiarito il concetto per me. –

+0

@KresimirNesek: 'PartialFunction' (e pattern matching) è uno degli strumenti più importanti e utili in scala. Vedi '9. Sezione "Pattern matching" in [Informazioni tag Scala] (http://stackoverflow.com/tags/scala/info). – senia

Problemi correlati