了解futureMongo中的未来[Option [T]]

时间:2014-09-24 13:21:34

标签: mongodb scala playframework-2.0 future reactivemongo

我在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语句吗?

2 个答案:

答案 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)

您有多种选择可供选择:

  • andThen
  • 地图
  • for comprehension

使用map,您将获得链中执行的最后Future的结果。使用andThen,您将获得应用Future的第一个andThen的结果。

对于您的用例,formap操作都可以。我会像这样使用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