1概要



JDeferred


は、定型コードを記述せずに非同期トポロジを実装するために使用される小さな

Java

ライブラリ(

Groovy

もサポート)です。このフレームワークはhttp://api.jquery.com/jquery.ajax/[

JqueryのPromise/Ajax

]機能およびhttps://github.com/CodeAndMagic/android-deferred-object[

Android’s Deferred Object

]パターンに触発されています。

このチュートリアルでは、

JDeferred

とそのさまざまなユーティリティの使い方を説明します。


2 Mavenの依存関係


pom.xmlに次の依存関係を追加することで、どのアプリケーションでも

JDeferred__を使い始めることができます。

<dependency>
    <groupId>org.jdeferred</groupId>
    <artifactId>jdeferred-core</artifactId>
    <version>1.2.6</version>
</dependency>


https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.jdeferred%22%20AND%20a%3A%22jdeferred-coreで


JDeferred

プロジェクトの最新バージョンを確認できます。 %22[Central Mavenリポジトリ]。


3約束

エラーが発生しやすい同期

REST


API

呼び出しを呼び出す単純なユースケースを見て、APIから返されたデータに基づいて何らかのタスクを実行しましょう。

単純なJQueryでは、上記のシナリオは次のように対処できます。

$.ajax("/GetEmployees")
    .done(
        function() {
            alert( "success" );
        }
     )
    .fail(
        function() {
            alert( "error" );
        }
     )
    .always(
        function() {
            alert( "complete" );
        }
    );

同様に、

JDeferred

には、


Promise


およびhttps://が付属しています。 github.com/jdeferred/jdeferred/blob/master/subprojects/jdeferred-core/src/main/java/org/jdeferred2/Deferred.java[

Deferred

]インタフェースは、対応するオブジェクトにスレッドに依存しないフックを登録し、異なるカスタマイズをトリガします。そのオブジェクトステータスに基づくアクション。

ここで、

Deferred

はトリガーとして機能し、

Promise

はオブザーバとして機能します。

このタイプの非同期ワークフローは簡単に作成できます。

Deferred<String, String, String> deferred
  = new DeferredObject<>();
Promise<String, String, String> promise = deferred.promise();

promise.done(result -> System.out.println("Job done"))
  .fail(rejection -> System.out.println("Job fail"))
  .progress(progress -> System.out.println("Job is in progress"))
  .always((state, result, rejection) ->
    System.out.println("Job execution started"));

deferred.resolve("msg");
deferred.notify("notice");
deferred.reject("oops");

ここでは、各メソッドは異なる意味を持ちます。


  • done()

    – 保留中のアクションが延期されたときにのみトリガ

オブジェクトは正常に完了しました。
**

fail()

– 実行中に何らかの例外が発生したときにトリガします

保留オブジェクトに対する保留中のアクション
**

progress()

– 保留中のアクションが保留されるとすぐにトリガします

オブジェクトは実行を開始します。
**

always()

– 遅延オブジェクトの状態に関係なくトリガーします

デフォルトでは、遅延オブジェクトのステータスは

PENDING/REJECTED/RESOLVED

になります。


deferred.state()


メソッドを使ってステータスを確認できます。

ここで注意しなければならないのは、** 遅延オブジェクトのステータスが

RESOLVEDに変更されると、

そのオブジェクトに対して

reject

操作を実行できなくなることです。

同様に、オブジェクトのステータスが

REJECTEDに変更されると、

そのオブジェクトに対して

resolve

または

notify

操作を実行することはできません。違反があると、

IllegalStateExeption

が発生します。


4フィルター

最終結果を取得する前に、https://github.com/jdeferred/jdeferred/blob/master/subprojects/jdeferred-core/src/main/java/org/jdeferred2/DoneFilter.javaを使用して、遅延オブジェクトに対してフィルタリングを実行できます。[

DoneFilter

]。

フィルタリングが完了したら、スレッドセーフな遅延オブジェクトを取得します。

private static String modifiedMsg;

static String filter(String msg) {
    Deferred<String, ?, ?> d = new DeferredObject<>();
    Promise<String, ?, ?> p = d.promise();
    Promise<String, ?, ?> filtered = p.then((result) > {
        modifiedMsg = "Hello "  result;
    });

    filtered.done(r > System.out.println("filtering done"));

    d.resolve(msg);
    return modifiedMsg;
}


5パイプ

filterと同様に、

JDeferred

は洗練された投稿を実行するためにhttps://github.com/jdeferred/jdeferred/blob/master/subprojects/jdeferred-core/src/main/java/org/jdeferred2/DonePipe.java[

DonePipe

]インターフェースを提供します保留オブジェクト保留アクションが解決された後のアクションのフィルタリング。

public enum Result {
    SUCCESS, FAILURE
};

private static Result status;

public static Result validate(int num) {
    Deferred<Integer, ?, ?> d = new DeferredObject<>();
    Promise<Integer, ?, ?> p = d.promise();

    p.then((DonePipe<Integer, Integer, Exception, Void>) result > {
        public Deferred<Integer, Exception, Void> pipeDone(Integer result) {
            if (result < 90) {
                return new DeferredObject<Integer, Exception, Void>()
                  .resolve(result);
            } else {
                return new DeferredObject<Integer, Exception, Void>()
                  .reject(new Exception("Unacceptable value"));
            }
    }).done(r > status = Result.SUCCESS )
      .fail(r > status = Result.FAILURE );

    d.resolve(num);
    return status;
}

ここでは、実際の結果の値に基づいて、結果を拒否する例外を発生させました。


6. 延期マネージャ

リアルタイムのシナリオでは、複数の約束によって観測された複数の遅延オブジェクトを処理する必要があります。このシナリオでは、複数の約束を別々に管理することはかなり困難です。

そのため、

JDeferred

にhttps://github.com/jdeferred/jdeferred/blob/master/subprojects/jdeferred-core/src/main/java/org/jdeferred2/DeferredManager.java[

DeferredManager

]インタフェースを使用して、すべての約束

したがって、この共通オブザーバを使用して、すべての約束に対して共通のアクションを作成できます。

Deferred<String, String, String> deferred = new DeferredObject<>();
DeferredManager dm = new DefaultDeferredManager();
Promise<String, String, String> p1 = deferred.promise(),
  p2 = deferred.promise(),
  p3 = deferred.promise();
dm.when(p1, p2, p3)
  .done(result -> ... )
  .fail(result -> ... );
deferred.resolve("Hello Baeldung");

カスタムスレッドプールを持つhttps://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html[

ExecutorService

]を

DeferredManager

に割り当てることもできます。

ExecutorService executor = Executors.newFixedThreadPool(10);
DeferredManager dm = new DefaultDeferredManager(executor);

実際、

Promise

の使用を完全に無視して、https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html[

Callable

]インタフェースを直接定義して、仕事:

DeferredManager dm = new DefaultDeferredManager();
dm.when(() -> {
   //return something and raise an exception to interrupt the task
}).done(result -> ... )
  .fail(e -> ... );

** 7. スレッドセーフアクション+

**

ほとんどの場合、非同期ワークフローを処理する必要がありますが、場合によっては、すべての並列タスクの結果を待つ必要があります。

この種のシナリオでは、すべての延期タスクが終了するのを待つために

Object

’s

wait()

メソッドのみを使用できます。

DeferredManager dm = new DefaultDeferredManager();
Deferred<String, String, String> deferred = new DeferredObject<>();
Promise<String, String, String> p1 = deferred.promise();
Promise<String, String, String> p = dm
  .when(p1)
  .done(result -> ... )
  .fail(result -> ... );

synchronized (p) {
    while (p.isPending()) {
        try {
            p.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

deferred.resolve("Hello Baeldung");

あるいは、

Promise

インターフェースの

waitSafely()

メソッドを使用しても同じことができます。

try {
    p.waitSafely();
} catch (InterruptedException e) {
    e.printStackTrace();
}

上記の方法はどちらもほぼ同じ動作をしますが、2番目の手順では同期が不要なので、2番目の方法を使用することをお勧めします。


8 Androidの統合


JDeferred

は、Android Mavenプラグインを使用してAndroidアプリケーションと簡単に統合できます。

APKLIBをビルドするには、

pom.xml

に次の依存関係を追加する必要があります。

<dependency>
    <groupId>org.jdeferred</groupId>
    <artifactId>jdeferred-android</artifactId>
    <version>1.2.6</version>
    <type>apklib</type>
</dependency>


AAR

ビルドの場合は、

pom.xml

に次の依存関係を追加する必要があります。

<dependency>
    <groupId>org.jdeferred</groupId>
    <artifactId>jdeferred-android-aar</artifactId>
    <version>1.2.6</version>
    <type>aar</type>
</dependency>


9結論

このチュートリアルでは、

JDeferred

について調べましたが、これはさまざまなユーティリティです。

いつものように、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/libraries/src/main/java/com/baeldung/jdeffered[over on GitHub]から入手可能です。