Scala 仅当将来的计算完成时才返回页面

Scala 仅当将来的计算完成时才返回页面,scala,playframework,Scala,Playframework,我的应用程序中有一个使用Play Framework的控制器 def controllerMethod() = Action{ val someval = callToService() Ok(views.html.abc(someval)) } 服务类中的callToService方法: 当我从for循环中调用webservice时,比如说5次,每次我都在somerandomobject中设置一个属性。因为for循环中有一个webservice调用,它返回一个未来的[Response

我的应用程序中有一个使用Play Framework的控制器

def controllerMethod() = Action{
  val someval = callToService()
  Ok(views.html.abc(someval))
}
服务类中的callToService方法:

当我从for循环中调用webservice时,比如说5次,每次我都在somerandomobject中设置一个属性。因为for循环中有一个webservice调用,它返回一个未来的[Response],所以控制器返回页面时甚至没有得到someval的值,并且页面上没有显示任何数据

为了防止出现这种情况,我将块置于wait.resultfuture、timeout中,并给出了一些超时。这是个坏主意。我还可以做些什么,以便控制器仅在someval对象可用后返回页面?

选项1:

您可以通过组合从web服务返回的future,从callToService返回future。因此callToService将具有Future[SomeRandomObject]的返回类型,并将def更改为some

备选案文2:

对从webservice返回的future使用Await.result,其余代码将保持不变。但此选项阻止了选项1:

您可以通过组合从web服务返回的future,从callToService返回future。因此callToService将具有Future[SomeRandomObject]的返回类型,并将def更改为some

备选案文2:


对从webservice返回的future使用Await.result,其余代码将保持不变。但是这个选项阻碍了

我认为你误解了Play如何使用期货的本质。未来不需要在函数退出时完成,因为函数本身可以返回未来

假设您的服务中有一个函数,它返回一个包含字符串的Future:

def getSingleResult: Future[String]
要在控制器中处理此问题,可以将未来的成功完成映射到结果字符串

def singleSource = Action.async {
  // send the string in the body of a 200 response
  getSingleResult.map(str => Ok(str))
}
现在,假设您正在调用5个web服务,并且希望同时在控制器中处理结果。在本例中,webServiceX函数表示对web服务的调用;因为这些示例函数返回期货,所以我们得到了相同的效果

def webServiceCallA: Future[String] = // implementation
def webServiceCallB: Future[Int] = // implementation
def webServiceCallC: Future[Boolean] = // implementation
def webServiceCallD: Future[Foo] = // implementation
def webServiceCallE: Future[Bar] = // implementation
我们可以使用for comprehension来完成这些未来,并构造SomeRandomClass的实例来返回结果

case class SomeRandomClass(a: String, b: Int, c: Boolean, d: Foo, e: Bar)

def getUsingForComprehension: Future[SomeRandomObject] = {
    val eventualA = webServiceCallA
    val eventualB = webServiceCallB
    val eventualC = webServiceCallC
    val eventualD = webServiceCallD
    val eventualE = webServiceCallE
    for {
      a <- eventualA
      b <- eventualB
      c <- eventualC
      d <- eventualD
      e <- eventualE
    } yield SomeRandomClass(a, b, c, d, e)
  }

在任何时候,我们都不会阻止或明确等待未来的完成

我认为你误解了游戏如何利用未来的本质。未来不需要在函数退出时完成,因为函数本身可以返回未来

假设您的服务中有一个函数,它返回一个包含字符串的Future:

def getSingleResult: Future[String]
要在控制器中处理此问题,可以将未来的成功完成映射到结果字符串

def singleSource = Action.async {
  // send the string in the body of a 200 response
  getSingleResult.map(str => Ok(str))
}
现在,假设您正在调用5个web服务,并且希望同时在控制器中处理结果。在本例中,webServiceX函数表示对web服务的调用;因为这些示例函数返回期货,所以我们得到了相同的效果

def webServiceCallA: Future[String] = // implementation
def webServiceCallB: Future[Int] = // implementation
def webServiceCallC: Future[Boolean] = // implementation
def webServiceCallD: Future[Foo] = // implementation
def webServiceCallE: Future[Bar] = // implementation
我们可以使用for comprehension来完成这些未来,并构造SomeRandomClass的实例来返回结果

case class SomeRandomClass(a: String, b: Int, c: Boolean, d: Foo, e: Bar)

def getUsingForComprehension: Future[SomeRandomObject] = {
    val eventualA = webServiceCallA
    val eventualB = webServiceCallB
    val eventualC = webServiceCallC
    val eventualD = webServiceCallD
    val eventualE = webServiceCallE
    for {
      a <- eventualA
      b <- eventualB
      c <- eventualC
      d <- eventualD
      e <- eventualE
    } yield SomeRandomClass(a, b, c, d, e)
  }
在任何时候,我们都不会阻止或明确等待未来的完成