我在Scala中编写了一个play 2.3应用程序。 我使用mongoDB数据库和ReactiveMongo驱动程序。 我调用读取/写入/更新db中的日期的方法返回Future [Option [T]]。 我的问题是:如果我有一个方法,首先更新文档,并在阅读更新的文档后,我需要一个onComplete语句? 例如:
def updatePasswordInfo(user: LoginUser,info: PasswordInfo): scala.concurrent.Future[Option[BasicProfile]] = {
import LoginUser.passwordInfoFormat //import the formatter
//the document query
val query = Json.obj("providerId" -> user.providerId,
"userId" -> user.userId
)
val newPassword = Json.obj("passswordInfo" -> info)// the new password
//search if the user exists and
val future = UserServiceLogin.update(query, newPassword) //update the document
for {
user <- UserServiceLogin.find(query).one
} yield user //return the new LoginUser
}
是否正确?我需要在使用UserServicelogin.find(query).one
语句之前使用onComplete语句吗?
答案 0 :(得分:1)
您有概念错误。在检索用户之前,您不是在等待更新完成,因此实际上最终可能会在更新之前检索用户。
修复非常简单:
for {
_ <- UserServiceLogin.update(query, newPassword)
user <- UserServiceLogin.find(query).one
} yield user
for-comprenehsion中的期货会被剔除,因此您将始终返回更新后的用户。
这有效的原因是,for-comprehension desugars to
UserServiceLogin.update(query, newPassword).flatMap { _ =>
UserServiceLogin.find(query).one.map { user =>
user
}
}
所以只有find
方法成功后才会执行update
方法。
答案 1 :(得分:0)
您有多种选择可供选择:
使用map
,您将获得链中执行的最后Future
的结果。使用andThen
,您将获得应用Future
的第一个andThen
的结果。
对于您的用例,for
或map
操作都可以。我会像这样使用map
:
def updatePasswordInfo(user: LoginUser,info: PasswordInfo): scala.concurrent.Future[Option[BasicProfile]] = {
import LoginUser.passwordInfoFormat //import the formatter
//the document query
val query = Json.obj("providerId" -> user.providerId,
"userId" -> user.userId
)
val newPassword = Json.obj("passswordInfo" -> info)// the new password
//search if the user exists and
val future = UserServiceLogin.update(query, newPassword) //update the document
future.map( x => UserServiceLogin.find(query).one )
}
参考文献:
[1] http://www.scala-lang.org/api/current/#scala.concurrent.Future
[2] http://docs.scala-lang.org/sips/completed/futures-promises.html