2014-01-28 46 views
1

我是新玩框架2.我看过很多关于异步调用的例子: JavaAsync。但是,所有这些都发生在“控制器”层。这意味着在这些示例中,函数组合的结果总是“Result”对象,并且我还没有看到任何其他示例返回“Result”以外的任何其他示例。话虽如此,由于不同的设置,我需要返回布尔值。这是我的设置:如何在PlayFramework 2的服务层中进行异步调用?

我有一个服务层。因此,我的控制器从用户那里获取请求,将它传递给我的服务层,我的服务层与外部服务(在我的例子中是elasticsearch)通信,外部服务发送它的结果,服务层获取它并将它传递给控制器,...。

我的问题是,我的异步调用服务层中发生的(顺便说一句,我使用以防万一play2-elasticsearch插件):

 

    @Override 
    public Boolean saveTask(TaskInfo taskInfo){ 
     final TaskEntity taskEntity = EntityTransformer.createNewTaskEntity(taskInfo); 
     // save to es 
     F.Promise indexResponsePromise = taskEntity.indexAsync(); 
     return indexResponsePromise.map(new F.Function() { 
      @Override 
      public Boolean apply(IndexResponse indexResponse) throws Throwable { 
       if (indexResponse.getId().equals(taskEntity.id.toString())) { 
        return Boolean.TRUE; 
       } else { 
        return Boolean.FALSE; 
       } 
      } 
     }); 

    } 

 

有,上面的代码,我得到一个错误,告诉我saveTask方法应该返回'F.Promise'。现在的问题:

  1. 我怎样才能返回一个“布尔”而不是'F.Promise'?
  2. 如果返回'F.Promise',我该如何从中获得价值?

谢谢!

+0

你想要一个布尔值作为返回使用弹性搜索调用是漫长的操作? 我建议你删除返回类型并将其替换为在promise中执行的回调 –

回答

3

返回布尔值的唯一方法是阻止调用线程,直到该回复到达,这将是一个坏的(tm)的事情。

好的选择(看起来可能看起来很糟糕)是让异步性通过图层泄漏出去。所以,你让你的控制器异步,并让你的服务层返回F.Promise。这样,你可以让你的控制器方法完全异步并对布尔值作出反应,并在那一刻创建一个http回复。

1

下面是从游戏框架谷歌组的回应:

我认为,为了更好地了解情况,我们需要后退一步。

当你异步操作时,你面临着一个选择。你可以是端到端的异步,或者你可以在某个时候阻止并避免异步(但是不惜代价!)。

因此,要采取您的问题,理想情况下saveTake将返回F.Promise<Boolean>,而不是Boolean。然后,无论什么调用saveTask异步操作该布尔值,等等,直到你到达控制器。然后控制器将采取Future<Result>而不是简单的Result。此时,该代码路径始终是异步的。 (好吧,忽略你的代码库中的其他内容)

一旦你有一个F.Promise<Boolean>,你可以在F.Promise上使用不同的高阶函数来异步操作。例如,如果您查看F.Promise的API,则会看到map函数。

您将创建一个F.Function,这需要Boolean作为其唯一的输入参数和返回B一个(无论何种B是因为F.Function是通用的)。这就是所谓的映射。

您不必直接操作您的布尔值,而是将这些函数链接到您的承诺上,只执行每个函数,因为前面的结果是可用的,并且所有这些都是异步完成的。