Play Framework 2.4顺序运行多个Promises

时间:2016-04-18 17:45:13

标签: akka playframework-2.4

我有一个Play 2.4(基于Java)的应用程序,其中一些后台Akka任务实现为返回Promise的函数。

  • Task1通过银行Rest API下载银行对帐单。
  • Task2处理语句并将其与客户配对。
  • Task3进行其他一些处理。

在Task1完成其工作之前,Task2无法运行。 Task3无法在Task2之前运行。我试图通过这样的Promise.map()序列运行它们:

protected F.Promise run() throws WebServiceException {
        return bankAPI.downloadBankStatements().map(
                result -> bankProc.processBankStatements().map(
                        _result -> accounting.checkCustomersBalance()));
}

我的印象是,第一张地图将等到Task1完成,然后它将调用Task2,依此类推。当我查看应用程序(任务正在将一些调试信息写入日志)时,我可以看到,这些任务是并行运行的。

我还试图使用Promise.flatMap()Promise.sequence()但没有运气。任务总是并行运行。

我知道Play本质上是非阻塞应用程序,但在这种情况下我真的需要按正确顺序执行操作。

是否有关于如何以选定的顺序运行多个Promise的一般做法?

2 个答案:

答案 0 :(得分:0)

您已将第二个电话嵌套到map,这意味着此处发生的是

  1. processBankStatements
  2. checkCustomerBalance
  3. downloadBankStatements
  4. 相反,你需要链接它们:

    protected F.Promise run() throws WebServiceException {
        return bankAPI.downloadBankStatements()
                      .map(statements -> bankProc.processBankStatements())
                      .map(processedStatements -> accounting.checkCustomersBalance());
    }
    

    我注意到你没有使用result_result(为了清楚起见我已重命名) - 这是故意的吗?

答案 1 :(得分:0)

好吧,我找到了解决方案。正确答案是:

如果你按照我的方式链接多个Promise。这意味着,作为map()函数的回报,您期望另一个Promise.map()函数等等,您应该遵循以下规则:

  • 如果您要从地图中返回非期货,请使用map()
  • 如果您要从地图中返回更多期货,则应使用flatMap()

我的案例的正确代码段是:

return bankAPI.downloadBankStatements().flatMap(result -> {
        return bankProc.processBankStatements().flatMap(_result -> {
            return accounting.checkCustomersBalance().map(__result -> {
                return null;
            });
        });
});

这个解决方案很久以前就被提出来了,但最初并没有起作用。问题是,我有一个隐藏的Promise.map()内部函数downloadBankStatements()所以在这种情况下flatMaps链被破坏了。