5

Web サービスから詳細を入力したいモデルがあります。サーバースレッドをブロックしないように、これを非同期で行いたいと思います。ログインサービスだとしましょう。

ここでやりたいことは、リモート サーバーにリクエストを送信し、最終的に User モデル オブジェクトを返すことです。したがって、メソッドのシグネチャは次のようになります。

public static User loginUser(String username, String password) {

Web サービスへの非同期呼び出しを行うには、次を使用する必要があることを理解していますPromise

Promise<WS.Response> wsPromise = WS.url("http://myserver.com/login")
            .setContentType("application/json; charset=utf-8")
            .post("... the username and password ...");

まだリクエストを開始していません。get()このオブジェクトを呼び出して、サービスへのブロッキング呼び出しを行うことができます。これは機能します。

これを非同期で行うには、これをマップして何らかの方法で実行する必要があると考えました。

Promise<User> resultPromise = wsPromise.map(new F.Function<WS.Response, User>() {
    @Override
    public User apply(WS.Response response) throws Throwable {
        System.out.println(response.getBody());
        return new User(... based on something extracted from the returned JSON ...);
    }
});

この操作をトリガーするにはどうすればよいですか? を呼び出すget()と、呼び出しは行われresultPromiseますが、最終的にタイムアウト例外が発生します。async(...)のみを返すため、メソッドを使用できませんResult

他の例 ( https://github.com/jroper/play-promise-presentation/blob/master/src/main/java/controllers/Application.java ) を見ると、これがパターンのようです。つまり、常に Result オブジェクトを返したいと考えています。ただし、オブジェクトを照会することはできず、Resultその特定のオブジェクトをユーザーに送信する予定はありません。

実際、これらの例は、Web サービスを呼び出し、JSON の結果をオブジェクトにマップし、すぐにそれらを同じ JSON にマップするように見えます。ユーザー (私の場合) を呼び出し元の関数に戻したい場合は、あまり役に立ちません。

正直に言うと、とにかく、これが非同期であることに少し戸惑っています (ご想像のとおり)。特に、Web サービスが応答を返すまで待機する必要があるため、これは実際にはブロック アクションです。ドキュメントは、Promise/Futureパターンを使用するとこのブロックが回避されることを示しているようです。

要点: Play Framework サーバーでスレッドをブロックせずに、Web サービス コールバックの結果をモデル オブジェクトにマップするにはどうすればよいでしょうか?

私の Play フレームワークの経験不足を悪用してください...

4

2 に答える 2

1

.get()またはWS 呼び出しで.post(...)、実際にWS 呼び出しをトリガーして外に出ます。(混同しないでください...それらはまったく異なります)。WS.get()myPromise.get()

この種の設計を完全に非同期に保つ秘訣は、Promise をコントローラーの応答からずっと下に置くことです。

これを行うには、Promise APIのmap()flatMat()、およびメソッドを適切に使用する必要があります。sequence()

特定のケースでは、WS 呼び出しが返されたときに発生する処理を行うコードmap()で WS 呼び出しの結果を使用します。ここで、応答を使用して実際に処理を行います。

flatMapこのパラダイムは、"for Comprehensions" を使用すると Scala の方が簡単ですが、呼び出しで終了するネストされた呼び出しのチェーンを使用する Java でも可能mapです。

于 2014-03-31T16:36:42.860 に答える