将多个承诺组合成一个承诺PlayFramework 2.4

200*_*0ok 3 java json promise playframework playframework-2.0

我正在尝试学习Play Framework 2.4.我正在尝试使用Promise以异步方式访问不同的网页.以下是代码:

final long start = System.currentTimeMillis();

F.Function<WSResponse,Long> timing = new F.Function<WSResponse, Long>() {
    @Override
    public Long apply(WSResponse wsResponse) throws Throwable {
        return System.currentTimeMillis()-start;
    }
};
F.Promise<Long> google = ws.url("http://www.google.com").get().map(timing);
F.Promise<Long> yahoo = ws.url("http://www.yahoo.com").get().map(timing);
F.Promise<Long> bing = ws.url("http://www.bing.com").get().map(timing);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我正在使用get函数来获取所请求的页面并将结果放入Future Promise中.然后我转换/映射到long.我无法做的是如何将这三个承诺组合成一个,一旦所有三个承诺被兑换成转换/映射到json并返回结果.在Play的早期版本中,它可能已经完成F.Promise.waitAll(google,yahoo,bing).map(...)但是我无法在Play 2.4中完成.请指教

编辑1:根据下面的答案,我使用如下序列:

return F.Promise.sequence(google, yahoo, bing).map(new F.Function<List<Long>, Result>() {
            @Override
            public Result apply(List<Long> longs) throws Throwable {
                Map<String, Long> data = new HashMap<String, Long>();
                data.put("google", google.get());
                data.put("yahoo", yahoo.get());
                data.put("bing", bing.get());
                return ok(Json.toJson(data));
            }
        });
Run Code Online (Sandbox Code Playgroud)

但是,我收到错误,无法解析google.get()方法,并且无法应用Json.我在这里失踪了什么?

编辑2. Json错误是通过使用修复return ok((JsonNode) Json.toJson((Writes<Object>) data));然而,我仍然无法解决之前的错误,即google.get()方法无法在行中解决data.put("google", google.get());

编辑3.似乎Play2.4没有get()方法,一旦兑换了Promise的值就返回它.那我该怎么用?

Ste*_*ner 6

waitAll已被取代F.Promise.sequence.

来自文档

public static <A> F.Promise<java.util.List<A>> sequence(java.lang.Iterable<F.Promise<A>> promises)

将给定的承诺合并为结果列表的单一承诺.排序操作在默认的ExecutionContext中执行.

参数:promises - 要结合的承诺

返回:单个promise,其方法作用于已兑换承诺列表

更新

关于问题的后半部分,您不需要打电话,.get()因为承诺已经完成.

事实上,你可以摆脱各个promise变量,然后直接将它们传递给序列.结果列表将包含相同顺序的结果(Google首先是雅虎,然后是Bing,在这种情况下是Bing).

整个事情应该是这样的:

package controllers;

import java.util.HashMap;
import java.util.Map;
import play.libs.F;
import play.libs.Json;
import play.libs.ws.WS;
import play.libs.ws.WSResponse;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Results;

public class Application extends Controller {

    public F.Promise<Result> index() {
        final long start = System.currentTimeMillis();
        final F.Function<WSResponse,Long> timing = response -> System.currentTimeMillis() - start;

        return F.Promise.sequence(WS.url("http://www.google.com").get().map(timing),
                                  WS.url("http://www.yahoo.com").get().map(timing),
                                  WS.url("http://www.bing.com").get().map(timing))
                        .map(list -> {
                            Map<String, Long> data = new HashMap<>();
                            data.put("google", list.get(0));
                            data.put("yahoo", list.get(1));
                            data.put("bing", list.get(2));
                            return data;
                        })
                        .map(Json::toJson)
                        .map(Results::ok);
    }

}
Run Code Online (Sandbox Code Playgroud)

最后,由于Play 2.4需要Java 8,这是一个玩lambdas的好机会!