我在scala play控制器方法中返回正确的类型有问题,有人可以在这里给我一个提示吗?我正在使用comprehantion来处理两个返回Future的服务方法,我想优雅地处理结果和错误。
这样做的最佳做法是什么?
test2.reset_index(inplace=True)
test2['index'] = test2['index'].dt.tz_localize('UTC').dt.tz_convert('US/Eastern').dt.tz_localize(None)
index groups value
0 2016-08-31 18:08:12 A 1
1 2016-08-31 18:08:12 NaN 1
2 NaT A 3
错误:
def registerUser = Action { implicit request =>
Logger.info("Start play actoin")
RegisterForm.form.bindFromRequest.fold(
formWithErrors => {
BadRequest(views.html.register(formWithErrors))
},
formData => {
val registerResult = for {
reCaptchaOk <- registerUserService.checkRecaptcha(formData.gRecaptchaResponse)
userId <- registerUserService.registerUser(formData) if reCaptchaOk
} yield userId
registerResult.map(
result => Redirect(routes.DashboardController.dashboard).withSession("USER_ID" -> result.toString))
.recover{
e => handleRegisterError(e)
}
})
}
def handleRegisterError(cause: Throwable)(implicit request: Request[_]) : Result = {
val form = RegisterForm.form.bindFromRequest
cause match {
case dae: DataAccessException =>
val globalError = dae.getCause.asInstanceOf[PSQLException].getSQLState match {
case "23505" => GlobalMessages(Seq(GlobalMessage(Messages("errors.db.userAlreadyExists") ,ERROR)))
case _ => GlobalMessages(Seq(GlobalMessage(Messages("errors.system.error"),ERROR)))
}
BadRequest(views.html.register(form,globalError))
case _ =>
BadRequest(views.html.register(form))
}
答案 0 :(得分:1)
您需要部分功能来恢复未来的故障:
def handleRegisterError(implicit request: Request[_]): PartialFunction[Throwable, Result] = {
case dae: DataAccessException =>
val form = RegisterForm.form.bindFromRequest
val globalError = dae.getCause.asInstanceOf[PSQLException].getSQLState match {
case "23505" => GlobalMessages(Seq(GlobalMessage(Messages("errors.db.userAlreadyExists"), ERROR)))
case _ => GlobalMessages(Seq(GlobalMessage(Messages("errors.system.error"), ERROR)))
}
BadRequest(views.html.register(form, globalError))
case _ =>
val form = RegisterForm.form.bindFromRequest
BadRequest(views.html.register(form))
}
然后将控制器代码更改为
registerResult
.map { result =>
Redirect(routes.DashboardController.dashboard).withSession("USER_ID" -> result.toString)
}
.recover {
handleRegisterError
}
另请注意,您需要异步操作,即
def registerUser = Action.async { implicit request =>
...
}
因为您没有返回Result
而是Future[Result]
。您可以在Play docs中找到有关操作的更多信息。
如果您查看recover
的{{1}}方法的文档(请参阅here),您会发现它需要Future
。
部分函数就像普通函数一样,但它们可能会拒绝某些值(例如,这里,recover方法不接受所有异常,只接受正文中指定的异常)。 定义部分函数需要特殊的语法。它非常像模式匹配,但没有匹配表达式。
pf: PartialFunction[Throwable, U]
这里我们使用内联的部分恢复函数,因此将自动推断类型,但如果要将recover定义为单独的函数,则需要显式声明其类型。
在大多数情况下,部分函数语法(没有Future(someAsyncWork).recover {
case my: MyException => ....
case _ => ....
}
关键字的模式匹配)非常简洁和方便,但有时您需要更多。
例如,请注意使用此语法,我们必须在recover函数中复制部分代码(match
)。
虽然在您的情况下可能有更好的解决方案,但您始终可以将普通功能转换为部分功能。首先,您需要定义类型val form = RegisterForm.form.bindFromRequest
的函数,然后您可以使用Function#unlift
将其转换为所需的部分函数。
您也可以直接从PartialFunction
继承并实施其两种方法(apply和isDefinedAt)。