2017-10-31 4 views
0

Java CompletableFuturesを使用して一連の非同期タスクを連鎖させています。コードは次のようなものになります。Javaを `CompletablyFuture.exceptionally`を使用して、オプションで例外を継続します。

CompletableFuture<Result> doTasks(final TaskId id) { 
    return firstTask.workAsync(id) 
      .thenComposeAsync(__ -> secondTask.workAsync(id)) 
      .thenComposeAsync(__ -> thirdTask.workAsync(id)) 
      .thenApplyAsync(__ -> fourthTask.workAsync(id)); 
} 

をしかし、firstTask.workAsyncは仕事がすでにこのような状況ではOKである、完了したので、私はちょうどそれを無視してチェーンを続けていきたいと考えていることを示す例外がスローされます。

もちろん、私は例外を扱うことができる別の関数でそのビットをラップすることができますが、CompletableFutureチェーンでそれを直接処理し、他の例外をすべてスローする方法がありますか?

私はCompletableFuture.exceptionallyを使用することを提案しましたが、私が見ているオンラインの例はすべて役に立たず、ちょうどnullを返します。これはチェーンを殺すようです。この場合、どうすれば使用できますか?

答えて

0

CompletableFuture.exceptionallyCompletableFutureで例外が発生した場合でも処理を続けることができます。簡単に言えば、例外のタイプをチェックする必要があります。例外が続く場合は、新しいCompletableFutureを返すことができます。結果はチェーンを介して使用されないため、空にすることができます。

CompletableFuture<Result> doTasks(final TaskId id) { 
    return firstTask.workAsync(id) 
      .exceptionally(t -> { 
       // Will continue down the chain if matches 
       if (t instanceof TotallyOkException) { 
        return null; 
       } 

       // This will throw an ExecutionException. I convert it to a RuntimeException here 
       // because I don't want to add throws statements up the chain. 
       throw new RuntimeException(t); 
      }) 
      .thenComposeAsync(__ -> secondTask.workAsync(id)) 
      .thenComposeAsync(__ -> thirdTask.workAsync(id)) 
      .thenApplyAsync(__ -> fourthTask.workAsync(id)); 
} 

この場合、すべての非TotallyOkException例外がスローされます。

+1

'return CompletableFuture.completedFuture(null)'ではなく 'return null'を意味すると思いますか? –

+0

@JoeC nullを返さないでチェーンを殺す?それは期待通りに動作しますが、タスク2-4を実行したい場合は、CompletableFutureを返す必要はありませんか? – EmptyArsenal

+1

これはシグニチャです: '例外的に(関数 fn)'。したがって、これは 'CompletableFuture >'がある場合にのみ機能します。ヌルを返すとチェーンが停止する理由はありません。 –

0

あなたのexceptionally機能でnullを返すことは、それ自体でチェーンを殺すことはありません。それがチェーンを殺す唯一の方法は、下流の機能でのヌル処理がなく、NullPointerExceptionを引き起こした結果です。

exceptionally機能は、いくつかのタイプの例外を処理するように設定することができます。たとえば:

return firstTask.workAsync(id) 
     .thenComposeAsync(firstResult -> secondTask.workAsync(id)) 
     .exceptionally(t -> { 
          if (t instanceof TransientException) { 
           return getUsingBackupMethod(id); 
          } 
          throw new RuntimeException(t); 
         }); 

このexceptionally関数は(事実上)最初の二つのタスクのいずれかからスローされた例外をキャッチします。

関連する問題