Ich habe Code in meiner Play-Framework-App, der eine JSON-Anfrage analysiert und sie verwendet, um die Daten eines Benutzers zu aktualisieren. Das Problem ist, dass ich eine Future[Result]
zurückgeben muss, aber meine userDAO.update
Funktion gibt eine Future[Int]
zurück, also habe ich geschachtelte Zukünfte.Wie verschachtelte Zukunft in Scala loswerden?
Ich habe verwendet Await
, die nicht sehr gut ist. Wie kann ich diesen Code umschreiben, um die verschachtelte Zukunft zu vermeiden?
def patchCurrentUser() = Action.async { request =>
Future {
request.body.asJson
}.map {
case Some(rawJson) => Json.fromJson[User](rawJson).map { newUser =>
val currentUserId = 1
logger.info(s"Retrieving users own profile for user ID $currentUserId")
val futureResult: Future[Result] = userDAO.findById(currentUserId).flatMap {
case Some(currentUser) =>
val mergedUser = currentUser.copy(
firstName = newUser.firstName // ... and the other fields
)
userDAO.update(mergedUser).map(_ => Ok("OK"))
case _ => Future { Status(404) }
}
import scala.concurrent.duration._
// this is bad. How can I get rid of this?
Await.result(futureResult, 1 seconds)
}.getOrElse(Status(400))
case _ => Status(400)
}
}
aktualisieren:
Sod Gesetz: Kurz nach dieser Entsendung ich es hat geklappt:
Future {
request.body.asJson
}.flatMap {
case Some(rawJson) => Json.fromJson[User](rawJson).map { newUser =>
val currentUserId = 1
userDAO.findById(currentUserId).flatMap {
case Some(currentUser) =>
val updatedUser = currentUser.copy(
firstName = newUser.firstName
)
userDAO.update(updatedUser).map(_ => Ok("OK"))
case _ => Future { Status(404) }
}
}.getOrElse(Future(Status(400)))
case _ => Future(Status(400))
}
Aber ist es eine elegantere Art und Weise? Es scheint, als ob ich ganz frei um Future()
pfeffern würde, was wie ein Code-Geruch aussieht.
Vermeiden Sie einfach die 'Zukunft {request.body.asJson}'. Dies wird sowieso in einem eigenen Thread ausgeführt. Vermeide auch 'Future (Stauts (xx))', weil das unnötig eine asynchrone Berechnung erzeugt. Was Sie wollen, ist 'Future.successful' – rethab
@rethab Danke für den Tipp. Ich wusste nicht über 'Future.successful'. Aber die 'Zukunft {request.body.asJson}' war so, dass ich die async Aktion verwenden und die 'Zukunft' zurückgeben konnte, die mit dem Abrufen des Benutzers von der DB verbunden ist ... (also nur, um den Typprüfer glücklich zu machen) – jbrown
ich auch entdeckte, dass play 'body parser' liefert, von denen einer eine' 400' zurückgibt, wenn er die Anfrage nicht nach JSON parsen kann. Tun Sie dies mit 'Action.async (parse.json)' anstatt nur 'Action.async', und das bedeutet, dass' request.body' ein 'JsValue' ist, der um eine weniger' Future' geht. – jbrown