同时有两个承诺

时间:2016-04-07 12:32:54

标签: java playframework playframework-2.4

我正在开发一个Play应用程序,它可以从其他第三方服务进行大量通信(检索数据)。我想要做的是"结合"每个请求的结果。

更准确。我有三个外部WSRequest,每个都封装在一个类中,该类有一个方法可以执行请求,检索JSON String并返回一个对象列表,这些对象基本上是JSON的反序列化版本。非常简化,它可以简化为这样的东西。

Class A {
    function F.Promise<List<ObjA>> call();
}
Class B {
    function F.Promise<List<ObjB>> call(Integer id);
}
Class C {
    function F.Promise<List<ObjC>> call();
}

从我的控制器,我调用A,B和C的对象,做一些处理并返回一个结果,这是另一个对象的JSON字符串(让我们称之为ObjD)。

在我的控制器中,我有类似的东西:

public F.Promise<Result> compute() {
   A a = new A();
   B b = new B();
   C c = new C();

  List<ObjA> objAList = a.call().get(TIMEOUT);
  List<ObjB> objBList = b.call(objAList.get(0).getId()).get(TIMEOUT);
  List<ObjC> objCList = c.call().get(TIMEOUT);

  // compute something using the three lists. This will create an object objD

  return F.Promise.promise(() -> ok(Json.toJson(objD)));
}

List的结果取决于A的结果(因此无法同时调用它们)。很明显,我可以这样:

public F.Promise<Result> compute() {
    A a = new A();
    B b = new B();
    C c = new C();

    List<ObjC> objCList = c.call(0.get(TIMEOUT);
    return a.call().map(objAList -> {
       List<ObjB> objBList = b.call(objAList.get(0).getId()).get(TIMEOUT);
       // compute and make objD
       return Json.toJson(objD);
    });
}

然而我不知道的是,是否(以及如何)同时执行对A和C的调用,并在收到两者后开始剩余的处理。因此,不是对C进行调用,等待结果,只有在调用A之后,我希望能够触发A和C调用,并且一旦接收到两者的结果,就可以进行结果所需的计算

由于

1 个答案:

答案 0 :(得分:1)

默认情况下,Play中的WS请求将执行异步。

这里的第一个问题是你强迫Play等待/同步。使用F.Promise#get()不是一个好主意。相反,你应该使用map / flatMap来操作响应 - 你可以通过调用服务A来部分地做。

如果你进一步了解F.Promise API - 有一个名为sequence的方法 - 你可以使用 - 只需在列表中收集你的所有承诺并致电F.Promise.sequence(myPromises) - 你会得到一个结果列表的单一承诺 - 然后您可以使用它来生成对象D.