我正在开发一个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调用,并且一旦接收到两者的结果,就可以进行结果所需的计算
由于
答案 0 :(得分:1)
默认情况下,Play中的WS请求将执行异步。
这里的第一个问题是你强迫Play等待/同步。使用F.Promise#get()不是一个好主意。相反,你应该使用map / flatMap来操作响应 - 你可以通过调用服务A来部分地做。
如果你进一步了解F.Promise API - 有一个名为sequence的方法 - 你可以使用 - 只需在列表中收集你的所有承诺并致电F.Promise.sequence(myPromises)
- 你会得到一个结果列表的单一承诺 - 然后您可以使用它来生成对象D.