Playframework 在不使用AsyncResult的情况下播放2个异步webservice调用

Playframework 在不使用AsyncResult的情况下播放2个异步webservice调用,playframework,playframework-2.0,Playframework,Playframework 2.0,Play 2允许您通过AsyncResult执行操作,这不会阻塞线程: public static Result feedTitle(String feedUrl) { return async( WS.url(feedUrl).get().map( new Function<WS.Response, Result>() { public Result apply(WS.Response response

Play 2允许您通过AsyncResult执行操作,这不会阻塞线程:

public static Result feedTitle(String feedUrl) {
    return async(
        WS.url(feedUrl).get().map(
            new Function<WS.Response, Result>() {
                public Result apply(WS.Response response) {
                    return ok("Feed title:" + response.asJson().findPath("title"));
                }
            }
        )
    );
}
公共静态结果feedTitle(字符串feedUrl){
异步返回(
WS.url(feedUrl.get().map(
新函数(){
应用公共结果(WS.Response响应){
返回ok(“提要标题:+response.asJson().findPath(“标题”);
}
}
)
);
}
这只有在您正在做简单的事情时才有效,比如直接将WS-call的结果传递给用户。但是,如果必须对结果执行其他操作,该怎么办

看,你似乎可以做到这一点:

Promise<Response> promise = WS.url("http://some.website.com").get();
Response response = promise.get();    // I've got the result, but I've also blocked
Promise-Promise=WS.url(“http://some.website.com).get();
Response=promise.get();//我得到了结果,但我也挡了

这显然是不理想的是否有一种方法可以在允许Play将执行传递给其他线程的同时执行异步调用?

好的,我找到了一种解决方案,尽管有点冗长。你能做的就是把一切都转移到演员身上

在全局对象中设置Actor,但将ActorRef保存在可以访问的位置

ActorRef myActor = Akka.system().actorOf(new Props(MyActor.class));
在您的Actor中,执行WS调用

public void onReceive(Object message) {
    WSRequestHolder request = WS.url("http://example.com");
    Response response = request.get().get();
    SomeResult result = doFurtherProcessing(response);
    getContext().sender().tell(result);    // reply the asking thread
}
在控制器中,只需将对参与者的调用包装为async()

公共静态结果方法(){
String message=“hello”;
异步返回(
asPromise(ask(myActor,message,1000)).map(新函数(){
公共结果应用(对象结果)抛出可丢弃{
返回ok(结果);
}
})
);
}
参考资料:

看看。这确实为我澄清了如何设计一个可以有多个promise调用的系统,以及如何将各种promise响应处理成更复杂的响应所需的内容,等等


最好的部分是——这个例子不觉得太冗长。它读起来非常好,理解起来非常简单。

没有必要仅仅为了推迟计算而创建参与者。 您可以使用
Promise.map(函数)
Promise.flatMap(函数)
将后处理绑定到异步调用。这些呼叫是可链接的

例如:

return async(WS.url("http://someservice.com/").get().map(
        new F.Function<play.libs.WS.Response, SomeData>() {
            @Override
            public SomeData apply (play.libs.WS.Response response) throws Throwable {
                SomeData someData = computeData(response);
                // Do extra computing here
                return someData;
            }
        }).map(
        new F.Function<SomeData, Result>() {
            @Override
            public Result apply(SomeData someData) throws Throwable {
                Result result = doSomethingElse(someData);
                return ok(result); 
            }
        })
 );
返回异步(WS.url(“http://someservice.com/“”.get().map(
新F.函数(){
@凌驾
public SomeData apply(play.libs.WS.Response-Response)抛出可丢弃{
SomeData SomeData=computeData(响应);
//在这里做额外的计算
返回一些数据;
}
}).地图(
新F.函数(){
@凌驾
公共结果应用(SomeData SomeData)抛出可丢弃{
结果=doSomethingElse(someData);
返回ok(结果);
}
})
);

只要最后一个
映射
返回一个
结果
,您就可以开始了。

第二场的备选答案

String url1 = String.format( "http://localhost:8080/site1", langcode );
String url2 = String.format( "http://localhost:8080/site2", langcode );
String url3 = String.format( "http://localhost:8080/site3", langcode );

F.Promise<WS.Response> remoteCall1 = WS.url(url1).get();
F.Promise<WS.Response> remoteCall2 = WS.url(url2).get();
F.Promise<WS.Response> remoteCall3 = WS.url(url3).get();

F.Promise<java.util.List<WS.Response>> promisesSequence = F.Promise.sequence(remoteCall1, remoteCall2, remoteCall3);

F.Promise<Result> resultPromise = promisesSequence.map(
    new Function<java.util.List<WS.Response>, Result>(){
        @Override
        public Result apply(java.util.List<WS.Response> responses){
            final StringBuffer sb = new StringBuffer();
            for(WS.Response r : responses){
                sb.append(r.getBody());
            }
            return ok( main.render("Output", sb.toString()));
        }
    });
String url1=String.format(“http://localhost:8080/site1“,langcode);
字符串url2=String.format(“http://localhost:8080/site2“,langcode);
字符串url3=String.format(“http://localhost:8080/site3“,langcode);
F.Promise-remoteCall1=WS.url(url1.get();
F.Promise-remoteCall2=WS.url(url2.get();
F.Promise-remoteCall3=WS.url(url3.get();
F.承诺承诺序列=F.承诺序列(remoteCall1、remoteCall2、remoteCall3);
F.Promise resultPromise=promissequence.map(
新函数(){
@凌驾
公共结果应用(java.util.List响应){
最终StringBuffer sb=新StringBuffer();
for(WS.Response r:responses){
sb.append(r.getBody());
}
返回ok(main.render(“Output”,sb.toString());
}
});

很好,谢谢。我最终成立了一个演员库来处理阻塞呼叫。当我需要完成某件事情时,我会向其中一个参与者“询问”一个“问题”,然后在播放控制器中返回async,并在映射函数中进行格式化。
String url1 = String.format( "http://localhost:8080/site1", langcode );
String url2 = String.format( "http://localhost:8080/site2", langcode );
String url3 = String.format( "http://localhost:8080/site3", langcode );

F.Promise<WS.Response> remoteCall1 = WS.url(url1).get();
F.Promise<WS.Response> remoteCall2 = WS.url(url2).get();
F.Promise<WS.Response> remoteCall3 = WS.url(url3).get();

F.Promise<java.util.List<WS.Response>> promisesSequence = F.Promise.sequence(remoteCall1, remoteCall2, remoteCall3);

F.Promise<Result> resultPromise = promisesSequence.map(
    new Function<java.util.List<WS.Response>, Result>(){
        @Override
        public Result apply(java.util.List<WS.Response> responses){
            final StringBuffer sb = new StringBuffer();
            for(WS.Response r : responses){
                sb.append(r.getBody());
            }
            return ok( main.render("Output", sb.toString()));
        }
    });