2016-07-24 21 views
2

Ich habe folgenden Code in meinem Stück 2 App:Wiedergabe Rahmen async Aktion: Zukunft recover nicht funktioniert

Controller:

... 
    def getUserById(id: Long) = Action.async { 
     try { 
      userService.findById(id) 
      .map(u => Ok(Json.toJson(u)) 
      .recover { 
       case e: Exception => Ok("Exception got") 
      } 
     } 
     } 
... 

Service:

... 
    override def findAll: Future[Seq[User]] = { 
    throw new Exception("Error 1") 
    } 
... 

Aber in Controller Ich kann keine Exception auslösen, die im Service ausgelöst wird (Wiederherstellungsblock wird irgendwie ignoriert). Stattdessen wird die Standardfehlerseite mit Ausnahme "Fehler 1" angezeigt.

Was mache ich falsch?

+1

Sie sollten 'Future.failed (new Exception ("Error 1"))' – dk14

Antwort

5

Ihr Code löst eine Ausnahme aus, bevor Sie eine Future Rückkehr, so sollten Sie entweder:

override def findAll: Future[Seq[User]] = Future { 
    throw new Exception("Error 1") 
} 

oder gerade:

override def findAll: Future[Seq[User]] = 
    Future.failed(new Exception("Error 1")) 

Auf diese Weise - eine Ausnahme wird innerhalb Future ‚s Instanz gewickelt werden , so kann jeder Teilnehmer es asynchron bekommen und durch recover verarbeiten. Andernfalls müssten Sie einen Fehler synchron verarbeiten, indem Sie ihn mit try{ findAll(...) } catch {...} umhüllen.

P.S. eine Ausnahme werfen is not referentially transparent, deshalb ist es manchmal schwierig, das Verhalten zu verstehen. Der Ansatz, bei dem der Fehler in eine Future verpackt wird, ist reiner, also würde ich das lieber machen, um Code klarer zu machen.

+0

wow, danke, es war auf den ersten Blick nicht offensichtlich, klar für mich jetzt. – Teimuraz

+0

übrigens, wie sollte fangen versuchen, wie in async-Aktion aussehen? Nach deiner Antwort habe ich ... versuchen {} catch {Fall e: Ausnahme => {val f = Zukunft {} f.map (_ => Ok ("Ausnahme !!!"))} ... Ist da Eine andere Möglichkeit, im Catch-Block in die Zukunft zurückzukehren? – Teimuraz

+1

@moreo Meine Antwort empfiehlt Ihnen eigentlich nicht, 'try {} catch' zu verwenden. Alles, was Sie brauchen, ist die gleiche Wiederherstellung, die Sie zuvor hatten, werfen Sie keine Ausnahme von Ihrer Methode - benutzen Sie 'def findAll = Future.failed (neue Exception (" Error 1 "))' stattdessen und dann etwas wie 'findAll. Karte (...). erholen (e => ok (Error-Code, e.getMessage)) ' – dk14