使用java“completablefuture.exceptional”可以选择通过异常继续

gz5pxeao  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(433)

我使用java将一系列异步任务链接在一起 CompletableFutures . 代码如下所示:

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

然而, firstTask.workAsync 抛出一个异常,指示工作已经完成,在这种情况下这是正常的,所以我只想忽略它并继续整个链。
当然,我可以将该位封装在一个单独的函数中,在这个函数中我可以处理异常,但是有没有一种方法可以直接在 CompletableFuture 链并继续抛出所有其他异常?
一位同事建议我使用 CompletableFuture.exceptionally ,但我在网上看到的所有示例都是完全无用的,只返回null,这看起来会扼杀链。在这种情况下我该怎么用?

50few1ms

50few1ms1#

completablefuture.Exceptional可用于在中获取异常时继续 CompletableFuture . 简言之,您需要检查异常的类型,如果您希望继续处理该异常,则可以返回一个新的异常 CompletableFuture ,可以为空,因为结果不会在链的下游使用。

  1. CompletableFuture<Result> doTasks(final TaskId id) {
  2. return firstTask.workAsync(id)
  3. .exceptionally(t -> {
  4. // Will continue down the chain if matches
  5. if (t instanceof TotallyOkException) {
  6. return null;
  7. }
  8. // This will throw an ExecutionException. I convert it to a RuntimeException here
  9. // because I don't want to add throws statements up the chain.
  10. throw new RuntimeException(t);
  11. })
  12. .thenComposeAsync(__ -> secondTask.workAsync(id))
  13. .thenComposeAsync(__ -> thirdTask.workAsync(id))
  14. .thenApplyAsync(__ -> fourthTask.workAsync(id));
  15. }

在这种情况下,它将抛出所有非- TotallyOkException 例外情况。

展开查看全部
ltskdhd1

ltskdhd12#

返回 null 在你的 exceptionally 函数本身不会杀死链。它杀死链的唯一方法是在下游函数中缺少空处理,并导致 NullPointerException .
你的 exceptionally 函数可以设置为处理某些类型的异常而不是其他类型的异常。例如:

  1. return firstTask.workAsync(id)
  2. .thenComposeAsync(firstResult -> secondTask.workAsync(id))
  3. .exceptionally(t -> {
  4. if (t instanceof TransientException) {
  5. return getUsingBackupMethod(id);
  6. }
  7. throw new RuntimeException(t);
  8. });

这个 exceptionally 函数将(有效地)捕获前两个任务中任何一个抛出的异常。

相关问题