【问题标题】:Understanding the Future[Option[T]] in reactiveMongo理解reactiveMongo中的Future[Option[T]]
【发布时间】:2014-11-19 00:21:13
【问题描述】:

我正在用 Scala 编写一个 play 2.3 应用程序。 我使用 mongoDB 数据库和 ReactiveMongo 驱动程序。 我调用来读取/写入/更新数据库中的日期的方法返回一个 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 语句是否正确?

【问题讨论】:

    标签: mongodb scala playframework-2.0 future reactivemongo


    【解决方案1】:

    你有概念错误。在检索用户之前,您无需等待更新完成,因此它实际上可能最终会在更新之前检索用户。

    修复非常简单:

    for {
      _ <- UserServiceLogin.update(query, newPassword)
      user <- UserServiceLogin.find(query).one
    } yield user
    

    for-compreehsion 中的 Futures 是序列化的,因此您将始终返回更新后的用户。

    之所以如此有效,是因为理解性降低了

    UserServiceLogin.update(query, newPassword).flatMap { _ =>
      UserServiceLogin.find(query).one.map { user =>
        user
      }
    }
    

    所以find 方法只有在update 方法成功后才会执行。

    【讨论】:

    • 为什么这样有效?为什么第二个语句在第一个语句完成后执行?
    【解决方案2】:

    您有多种选择:

    • 然后
    • 地图
    • 理解

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

    对于您的用例,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

    【讨论】:

      猜你喜欢
      • 2016-11-08
      • 2015-10-09
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2013-02-15
      • 2016-01-02
      • 2015-11-03
      相关资源
      最近更新 更多