Akka Play Framework 2.4多个承诺的顺序运行

Akka Play Framework 2.4多个承诺的顺序运行,akka,playframework-2.4,Akka,Playframework 2.4,我有一个Play2.4(基于Java)应用程序,其中一些后台Akka任务作为函数实现 Task1通过银行Rest API下载银行对账单 Task2处理语句并与客户配对 Task3执行其他一些处理 在Task1完成其工作之前,Task2无法运行。Task3不能在Task2之前运行。我试着通过Promise.map()的顺序运行它们,如下所示: protected F.Promise run() throws WebServiceException { return bankAP

我有一个Play2.4(基于Java)应用程序,其中一些后台Akka任务作为函数实现

  • 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本质上是非阻塞应用程序,但在这种情况下,我确实需要按正确的顺序进行操作


关于如何按所选顺序运行多个承诺,是否有常规做法?

您正在嵌套对
map
的第二个调用,这意味着这里发生的是

  • 处理银行对账单
  • 检查客户平衡
  • 下载银行对账单
  • 相反,您需要将它们链接起来:

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

    我注意到您没有使用
    result
    \u result
    (为了清楚起见,我已重命名)-这是故意的吗?

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

    如果你像我一样把多个承诺连在一起。这意味着,作为
    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()
    ,所以在这种情况下平面图链被破坏了。

    我使用的是
    F.Promise.Promise(lambda)
    ,它是由
    processBankStatements
    checkCustomerBalance
    返回的。承诺不能具有无效结果类型,因此我将从承诺返回null。所以结果是不相关的。这三个函数/承诺都在做一些数据库工作,它们不会返回任何内容。唯一的目的是按选定的顺序运行这些作业。我知道这不是一个很好的方法,也不是很好地使用播放功能,但在这种情况下,它是必要的。无论如何,谢谢你的建议。我会尝试的。如果不需要返回值,这没有问题,我只是检查答案是否完整。嗯,它不起作用。现在这三个承诺同时开始。你怎么知道?日志记录,还是别的什么?我建议在lambda中使用断点来确定执行顺序。它在数据处理中也是可见的。例如,在第一次运行时,下载10份银行对账单,处理0份(应为10份)。下一次运行时,将下载20多份银行对账单,处理10份。下载下一次运行5,处理20。看起来,一旦promise number 2运行,它就看不到新的最近的银行对账单,因为它们在那个时候不存在于数据库中。相反,它会看到以前下载的项目。在日志中,我看到所有三项任务同时开始,不同的结束时间取决于任务的持续时间