2

当我第一次使用 Play 2 进行开发时,我发现我在我的控制器中做了很多这样的事情(其中一个更简单的例子):

 val promUser = Akka.future(UserService.findByUsername(access.username))
  Async(
    promUser.map {
      _.map{
        user => {
          val promService = Akka.future(ServiceService loadOnlyWithUser (id,user.id.get))
          Async(
            promService.map { _.map { service =>
              Ok(toJson(service))
            }.getOrElse(BadRequest("not accessible"))}
          )
        }
      }.getOrElse {
        BadRequest("unauthorised")
      }
    }
  )

有一个单一的未来会更好吗?例如:

val promService = Akka.future{
    val userOption = UserService.findByUsername(access.username)
    userOption.map( user => {
      ServiceService loadOnlyWithDeveloper (id,user.id.get)
    }).getOrElse(None)

  }
  Async(
    promService.map { _.map { service =>
      Ok(toJson(service))
    }.getOrElse(BadRequest("unauthorised"))}
  )

我在想,一方面,控制器的许多期货/回报可能会增加开销,另一方面,将调用分组到一个未来将更具可读性,但会导致在 Akka 系统中运行更大的“线程”。对于更大的工作,我有一个额外的 Akka 系统,所以这些可能最多只包含 4 个 SQL 事务。就我可以从 apache bench 中解决的问题而言,上面的示例之间没有任何区别......我有什么遗漏吗?

4

1 回答 1

3

您的示例在性能上没有任何差异,因为它们是等效的。

当你写:

val promUser = Akka.future(UserService.findByUsername(access.username))

它不会开始评估它Future,它只会在您映射它时执行。

据我了解,您需要考虑期货组合。这是一个非常好的文档,我会推荐:http ://docs.scala-lang.org/sips/pending/futures-promises.html

那么,为了回答您的问题,如果您需要按顺序执行一堆查询,我认为如果您有多个期货,每个数据库访问一个期货,这不会有什么不同。例如检索一条记录,然后将其删除。

您可以利用 Futures 的地方(除了使您的应用程序非阻塞)是利用 for-comprehension 语法,以便您可以同时运行两个或多个异步 Futures,例如

for {
  authUser <- User.findById(request.authUserId)
  otherUser <- User.findById(id)
} yield (authUser, otherUser)

另外,我建议使用flatMap将您的 Futures 组合在一起,而不是使用多个Async{}块。这样,您将有效地将多个 Future 扁平Future[Future[Result]]化为一个可以是AsyncResult.

于 2012-12-11T23:59:55.040 回答