我可以做异步形成播放框架2.X(斯卡拉)验证? [英] Can I do async form validation in Play Framework 2.x (Scala)?

查看:135
本文介绍了我可以做异步形成播放框架2.X(斯卡拉)验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做一个真正的推理解游戏的异步权力,但发现很多矛盾就到异步调用适合的地方和地方的框架似乎密谋反对其使用。

I'm making a real push to understand the async powers of Play but finding a lot of conflict with regard to places where async invocation fits and places where the framework seems to conspire against its use.

我的例子涉及到表单验证。游戏允许被定义特设的约束 - 看到这个从文档:

The example I have relates to form validation. Play allows for ad-hoc constraints to be defined - see this from the docs:

val loginForm = Form(
  tuple(
    "email" -> email,
    "password" -> text
  ) verifying("Invalid user name or password", fields => fields match { 
      case (e, p) => User.authenticate(e,p).isDefined 
  })
)

尼斯和清洁。不过,如果我使用一个完全异步数据访问层(如ReactiveMongo),以 User.authenticate这样的电话(...)将返回未来,我在黑暗中,我怎么可以利用内置的形式绑定功能和异步工具双方力量从而来的。

Nice and clean. However, if I'm using a fully async data access layer (e.g. ReactiveMongo), such a call to User.authenticate(...) would return a Future and I'm thus in the dark as to how I can utilise the power of both the built in form binding features and the async tools.

这是一切都很好地宣传了异步的方式,但我感到沮丧,框架的某些部分不就打得这么好。如果验证已被同步完成,好像打败异步方法的点。例如 - 我已经使用动作组成时,碰到过类似的问题有关安全动作这将使到ReactiveMongo通话。

It's all well and good to publicise the async approach but I'm getting frustrated that certain parts of the framework don't play so well with it. If the validation has to be done synchronously, it seems to defeat the point of the async approach. I've come across a similar problem when using Action composition - e.g. a security related Action that would make a call to ReactiveMongo.

任何人都可以摆脱在哪里我的COM prehension已经追不上任何光线?

Can anyone shed any light on where my comprehension is falling short?

推荐答案

是的,在播放验证同步设计。我想这是因为假定大部分时间没有在表单验证没有I / O:字段值只是检查大小,长短,对正则表达式匹配,等等。

Yes, validation in Play is designed synchronously. I think it's because assumed that most of time there is no I/O in form validation: field values are just checked for size, length, matching against regexp, etc.

验证是建在<一个href=\"https://github.com/playframework/Play20/blob/2.1.0/framework/src/play/src/main/scala/play/api/data/validation/Validation.scala#L13\"><$c$c>play.api.data.validation.Constraint从验证的值存储功能,以为ValidationResult (或有效无效,没有地方放未来这里)。

Validation is built over play.api.data.validation.Constraint that store function from validated value to ValidationResult (either Valid or Invalid, there is no place to put Future here).

/**
 * A form constraint.
 *
 * @tparam T type of values handled by this constraint
 * @param name the constraint name, to be displayed to final user
 * @param args the message arguments, to format the constraint name
 * @param f the validation function
 */
case class Constraint[-T](name: Option[String], args: Seq[Any])(f: (T => ValidationResult)) {

  /**
   * Run the constraint validation.
   *
   * @param t the value to validate
   * @return the validation result
   */
  def apply(t: T): ValidationResult = f(t)
}

验证只是增加了用户自定义功能的其他限制。

verifying just adds another constraint with user-defined function.

所以我觉得在玩数据绑定只是不适合做I / O,同时验证。使其异步会使它更加复杂,更难使用,因此它保持简单。使每一件在框架code的就包裹在未来的数据工作 s是矫枉过正。

So I think Data Binding in Play just isn't designed for doing I/O while validation. Making it asynchronous would make it more complex and harder to use, so it kept simple. Making every piece of code in framework to work on data wrapped in Futures is overkill.

如果您需要使用的验证与ReactiveMongo,你可以使用 Await.result 。 ReactiveMongo无处不在返回期货,并且可以阻止,直到这些期货完成进去结果验证功能。是的,它会同时MongoDB的查询运行浪费一个线程。

If you need to use validation with ReactiveMongo, you can use Await.result. ReactiveMongo returns Futures everywhere, and you can block until completion of these Futures to get result inside verifying function. Yes, it will waste a thread while MongoDB query runs.

object Application extends Controller {
  def checkUser(e:String, p:String):Boolean = {
    // ... construct cursor, etc
    val result = cursor.toList().map( _.length != 0)

    Await.result(result, 5 seconds)
  }

  val loginForm = Form(
    tuple(
      "email" -> email,
      "password" -> text
    ) verifying("Invalid user name or password", fields => fields match { 
      case (e, p) => checkUser(e, p)
    })
  )

  def index = Action { implicit request =>
    if (loginForm.bindFromRequest.hasErrors) 
      Ok("Invalid user name")
    else
      Ok("Login ok")
  }
}

也许有办法不使用延续的线头,没有尝试过。

我认为这是很好的播放邮件列表中讨论这个问题,也许很多人都想做的播放数据绑定的异步I / O(例如,用于检查,对数据库中的值),所以有人可能会实现它的戏剧的未来版本

I think it's good to discuss this in Play mailing list, maybe many people want to do asynchronous I/O in Play data binding (for example, for checking values against database), so someone may implement it for future versions of Play.

这篇关于我可以做异步形成播放框架2.X(斯卡拉)验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆