两个 Promise 同时
Posted
技术标签:
【中文标题】两个 Promise 同时【英文标题】:Two Promises simultaneously 【发布时间】:2016-04-07 12:32:53 【问题描述】:我正在开发一个 Play 应用程序,该应用程序与其他 3rd 方服务进行大量通信(检索数据)。我想做的是“组合”每个请求的结果。
更准确地说。我有三个外部 WSRequest,每个都封装在一个类中,该类具有一个方法,该方法将执行请求、检索 JSON 字符串并返回一个对象列表,这些对象基本上是 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】:默认情况下,Play 中的 WS 请求是异步执行的。
这里的第一个问题是您强制 Play 等待/同步。使用F.Promise#get() 不是一个好主意。相反,您应该使用 map/flatMap 来操作响应 - 您部分是通过调用服务 A 来完成的。
如果您进一步查看 F.Promise API - 有一个名为 sequence 的方法 - 您可以使用该方法 - 只需将您的所有承诺收集在一个列表中并调用 F.Promise.sequence(myPromises)
- 您将获得一个针对结果列表 - 然后您可以使用它来生成对象 D。
【讨论】:
使用序列将不起作用,因为它期望两个 Promise 具有相同的类型。但是,一个是 Promise>,另一个是 Promise>。另外,我试图不再使用 .get(),但是我需要的计算依赖于来自所有三个请求的数据。以上是关于两个 Promise 同时的主要内容,如果未能解决你的问题,请参考以下文章