4

Play 2 では、スレッドをブロックしない AsyncResult を介して非同期 Web サービス呼び出しを行うことができます。

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"));
                }
            }
        )
    );
}

これは、WS 呼び出しの結果をユーザーに直接渡すなどの単純なことを行っている場合にのみ機能します。ただし、結果に対して追加の操作を行う必要がある場合はどうでしょうか。

documentationを見ると、これができるようです:

Promise<Response> promise = WS.url("http://some.website.com").get();
Response response = promise.get();    // I've got the result, but I've also blocked

これは明らかに理想的ではありません。Play が実行を他のスレッドに渡すことを許可しながら、非同期呼び出しを行う方法はありますか?

4

4 に答える 4

1

https://github.com/jroper/play-promise-presentationをご覧ください。これにより、複数の promise 呼び出しなどを行うことができるシステムを設計し、さまざまな promise 応答を操作して、より複雑な応答などに必要なものにする方法について、私にとって本当に明確になりました。

最良の部分は、例が冗長になりすぎていないことです。とても読みやすく、わかりやすいです。

于 2012-09-07T15:02:25.203 に答える
0

少し冗長ですが、解決策を見つけました。あなたができることは、すべてをアクターに移動することです。

グローバルオブジェクトにアクターを設定しますが、アクセスできる場所にActorRefを保存します。

ActorRef myActor = Akka.system().actorOf(new Props(MyActor.class));

アクターで、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()でラップするだけです。

public static Result method() {
    String message = "hello";
    return async(
        Akka.asPromise(ask(myActor, message, 1000)).map(new Function<Object, Result>() {
            public Result apply(Object result) throws Throwable {
                return ok(result);
            }
        })
    );
}

参照:http ://www.playframework.org/documentation/2.0.3/JavaAkka

于 2012-08-31T05:48:12.003 に答える
0

計算を遅らせるためだけにアクターを作成する必要はありません。Promise.map(Function<A, B>)およびを使用して、後処理を非同期呼び出しにバインドできますPromise.flatMap(Function<<A>, Promise<B>>)。これらの呼び出しは連鎖可能です。

例:

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); 
            }
        })
 );

map最後が a を返す限りResult、問題ありません。

于 2013-11-04T18:34:20.163 に答える