我正在创建一个用户注册模块。在提交(使用JSON)时,我想检查JSON是否正确解析。如果JSON中存在问题,我想返回错误。如果JSON是正确的,我想检查用户是否已经存在(查看名字)。数据在MongoDB中。我正在使用ReactiveMongoPlugin 0.10。我将使用'one'方法返回Future [Option [BSONDocument]]。如何在Action完成之前等待此Future完成?
方法1 - 使用Action并尝试自己处理Future的结果。代码不编译,也不知道如何等待Future完成
def registrationRequest = Action(parse.json) { request => {
Logger.debug("received message:" + request)
Logger.debug("received message:" + request.body)
val jr:JsResult[User2] = request.body.validate[User2]
Logger.debug( "jr is "+jr)
jr match {
case s:JsSuccess[User2] => {
val user = s.get
Logger.debug("opening database connection")
val driver = new MongoDriver()
val connection = driver.connection(List("localhost"))
val db = connection.db("website-db")
val collection = db.collection[BSONCollection]("users")
// the data from client is a JSON of type {user:{firstname:"name"}}. I have created code to parse the JSON
val query = BSONDocument("user"-> BSONDocument("firstname"->user.firstname))
Logger.debug("query is:"+query)
val result = collection.find(query).one
我想现在等待结果并返回Ok(Json.toJson(ack))或BadRequest(Json.toJson(ack))。我怎么做?我写了下面的代码,但我被困在两点(a)代码将等待未来完成(b)onComplete返回单位但Play的动作需要play.api.mvc.Result。我该怎么做?
//I guess data would be Success or Failure
result onComplete ( data =>
data match {
//If Success, value would be Some or None
case Success(value) => {
value match {
case None => { //no record. Can add
Logger.debug("No record from mongo: Can add")
val ack = Acknowledgment (1, "Welcome " + user.firstName + " " + user.lastName)
Logger.debug ("success ack Json:" + Json.toJson (ack) )
Ok (Json.toJson (ack) )
}
case Some(x) => { //duplicae record
Logger.debug("error from Mongo. Duplicate:"+x)
val ack = Acknowledgment(0,"duplicate: "+x.toString())
Logger.debug("fail ack:"+Json.toJson(ack))
BadRequest(Json.toJson(ack))
}
}
}
case Failure (e)=> {
Logger.debug("error from Mongo."+e)
val ack = Acknowledgment(0,"MongoDB Error: "+e.toString())
Logger.debug("fail ack:"+Json.toJson(ack))
BadRequest(Json.toJson(ack))
}
}) //onComplete returns Unit. Action needs play.api.mvc.Result
case f:JsError => {
Logger.debug("error: "+JsError.toFlatJson(f))
val ack = Acknowledgment(0,JsError.toFlatJson(f).toString())
Logger.debug("fail ack:"+Json.toJson(ack))
BadRequest(Json.toJson(ack))
}
}
}
方法2 - 我读到我应该使用Action.async,但我无法将各个部分放在一起。我遵循的第二种方法是使用Action.Async,但代码没有编译,因为它期望Future [SimpleResult]
def registrationRequest = Action.async(parse.json) { request => {
Logger.debug("received message:" + request)
Logger.debug("received message:" + request.body)
val jr:JsResult[User2] = request.body.validate[User2]
Logger.debug( "jr is "+jr)
jr match {
case s:JsSuccess[User2] => {
val user = s.get
Logger.debug("opening database connection")
val driver = new MongoDriver()
val connection = driver.connection(List("localhost"))
val db = connection.db("website-db")
val collection = db.collection[BSONCollection]("users")
val query = BSONDocument("user"-> BSONDocument("firstname"->user.firstName))
Logger.debug("query is:"+query)
//result is of type Future[Option[BSONDocument]]
val result = collection.find(query).one
result.map(option => option match {
case None => {
//no record. Can add
Logger.debug("No record from mongo: Can add")
val ack = Acknowledgment(1, "Welcome " + user.firstName + " " + user.lastName)
Logger.debug("success ack Json:" + Json.toJson(ack))
Ok(Json.toJson(ack))
}
case Some(x) => {
//duplicae record
Logger.debug("error from Mongo. Duplicate:" + x)
val ack = Acknowledgment(0, "duplicate: " + x.toString())
Logger.debug("fail ack:" + Json.toJson(ack))
BadRequest(Json.toJson(ack))
}
}
)
}
case f:JsError => {
Logger.debug("error: "+JsError.toFlatJson(f))
val ack = Acknowledgment(0,JsError.toFlatJson(f).toString())
Logger.debug("fail ack:"+Json.toJson(ack))
BadRequest(Json.toJson(ack)) //Action.async expect scala.concurrent.Future[play.api.mvc.SimpleResult]
}
}
}
答案 0 :(得分:1)
解决方案是使用返回Future [SimpleResult]的Action.async。在代码内部使用map和flatMap on Future返回Future [SimpleResult]。