将 Future[List[String]] 转换为 List[String]

3
我有以下代码:

Some(db.run(unionPermissionQuery.result).map(_.map(_.name).toList))

我遇到了以下错误:

[error]  found   : scala.concurrent.Future[List[String]]
[error]  required: List[String]
[error]           Some(db.run(unionPermissionQuery.result).map(_.map(_.name).toList)),
[error]                                                       ^
[error] one error found

所以我想,我需要将Future[List[String]]转换为List[String]。我是scala的新手,请原谅如果这太简单了。

完整代码:

  def find(loginInfo: LoginInfo): Future[Option[models.admin.User]] = {
val userQuery = for {
  dbLoginInfo <- loginInfoQuery(loginInfo)
  dbUserLoginInfo <- Userlogininfo.filter(_.logininfoid === dbLoginInfo.id)
  dbUser <- User.filter(_.userid === dbUserLoginInfo.userid)
} yield dbUser

db.run(userQuery.result.headOption).map { dbUserOption =>
  dbUserOption.map { user =>
    val permissionQuery = for {
      dbUserPermission <- Userpermission.filter(_.userid === user.userid)
      dbPermission <- Permission.filter(_.id === dbUserPermission.permissionid)
    } yield dbPermission

    val rolePermissionQuery = for {
      dbUserRole <- Userrole.filter(_.userid === user.userid)
      dbRole <- Role.filter(_.id === dbUserRole.roleid)
      dbRolePermission <- Rolepermission.filter(_.roleid === dbRole.id)
      dbPermission <- Permission.filter(_.id === dbRolePermission.permissionid)
    } yield dbPermission

    val unionPermissionQuery = permissionQuery union rolePermissionQuery

    models.admin.User(
      UUID.fromString(user.userid),
      user.firstname,
      user.lastname,
      user.jobtitle,
      loginInfo,
      user.email,
      user.emailconfirmed,
      Some(db.run(unionPermissionQuery.result).map(_.map(_.name).toList)),
      user.enabled)
  }
}

我只想获取用户并填写所有权限。包括用户个人权限和角色继承的权限。
是先获取用户,再根据用户ID执行另一个请求来获取权限更好吗?我不这么认为。

1
虽然我从未使用过“Future”,但我认为从“Future”中获取值的唯一方法是等待,这意味着调用STD-lib“Future”类的“result”。这就是“Future”的含义,不是吗? - ziggystar
2
请提供上下文。在 Play! 中,您可能应该始终避免 Await,因此我认为,您应该调整周围的代码以使用 Future - Odomontois
2个回答

6

期货的一般信息

您可以在http://docs.scala-lang.org/overviews/core/futures.html上找到所有有关期货的信息。

一种可能的方法是等待结果,但在生产应用程序中使用它不是很好。

val myFutureResult : Future[T] = Future {...}
val myResult : T = Await.result(myFutureResult, secondsToWait seconds)

通常情况下,您可以使用map函数对未来的结果进行组合处理,而不是等待结果并将其存储在变量中。只有在最后时刻才使用Await函数。

val myFutureResult : Future[T] = Future {...}
def myFunctionOnT(in: T) = ...

for {res <- myFutureResult } yield myFunctionOnT(res)

Play 和 Futures

Play 默认可以通过使用 Action.async {} 代替 Action{} 来处理 Future[T]。更多详细信息请查看:https://www.playframework.com/documentation/2.5.x/ScalaAsync

这些信息适用于扩展问题

db.run(unionPermissionQuery.result).map(_.map(_.name).toList).map { permission =>

models.admin.User(
  UUID.fromString(user.userid),
  user.firstname,
  user.lastname,
  user.jobtitle,
  loginInfo,
  user.email,
  user.emailconfirmed,
  Some(permission),
  user.enabled)
  }

但是我想将结果保存在一个变量中,而不是通过操作返回它。 - glarkou
1
它更像是注释,而不是真正的答案。 - Odomontois
3
这是一个答案。但问题的提出者很可能问错了问题。 - Seth Tisue

2

我来回答标题中的问题。

实现函数 Future[A] => A唯一合理方式(且没有时光机)是等待 future 完成,因为值 Future[A] 表示将在未来产生类型 A 的值。

检查您的库以获取正确的等待方法。对于 Scala std lib,它是 Await.result(),而不是 .result。如 Jean 所评论的。

请注意,等待是一个阻塞方法调用。如果您想避免这种情况(有一些很好的理由这样做),可以查看 Andreas 的答案。


3
根据Scala文档所示,阻塞并从scala.concurrent.Future中获取值的正确方式是使用Await.result()。请参见http://www.scala-lang.org/api/current/index.html#scala.concurrent.Future@result(atMost:scala.concurrent.duration.Duration)(implicitpermit:scala.concurrent.CanAwait):T 中的“此方法不应直接调用;请改用Await.result。”。 - Jean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接