我不了解你们,但是对我来说,当我看到一段repeated
的代码,并且在使用Services
并抛出异常时遇到了以下情况。如下所示,在每个CompletableFuture
块中,我都必须做exception handling
,该部分基本上会重复执行,具体取决于您将要拥有多少个可完成的期货。
CompletableFuture<Void> future1Of15 = CompletableFuture.supplyAsync(() -> {
List<SomePojo> somePojos = null;
try {
somePojos = someServiceThatThrowsException.getAll(SomePojo.class);
} catch (SomeException e) {
//Handle the exception
e.printStackTrace();
}
return somePojos;
}).thenAcceptAsync(result -> //do something with the result);
CompletableFuture<Void> future2Of15 = CompletableFuture.supplyAsync(() -> {
List<OtherPojo> otherPojos = null;
try {
otherPojos = someServiceThatThrowsException.getAll(OtherPojo.class);
} catch (SomeException e) {
//Handle the exception
e.printStackTrace();
}
return otherPojos;
}).thenAcceptAsync(result -> //do something with the result);
现在重复上述x
的次数,您会注意到try/catch
块已重复。就我而言,我大约有15-20
个这样的电话。
是否可以将上面的代码转换为1或2行代码?在stop repeating myself
内相对于exception handling
而言,supplyAsync lambda
的顺序是什么?
答案 0 :(得分:2)
只需向您的类添加一个执行所有重复代码的方法,并以Consumer<List<?>>
作为参数传递给最后一行的thenAcceptAsync
。
private CompletableFuture<Void> getAndAcceptAsync(Consumer<List<?>> resultProcessor) {
return CompletableFuture.supplyAsync(() -> {
List<SomePojo> somePojos = null;
try {
somePojos = someServiceThatThrowsException.getAll(SomePojo.class);
} catch (SomeException e) {
//Handle the exception
e.printStackTrace();
}
return somePojos;
}).thenAcceptAsync(resultProcessor);
}
然后您可以根据需要多次拨打此电话。
future1Of15 = getAndAcceptAsync(result-> { do something } );
future2Of15 = getAndAcceptAsync(result-> { do something else } );
答案 1 :(得分:2)
有 patterns 用于处理诸如功能编程失败。一种这样的模式是Try
monad,例如vavr提供了Java实现。
这些模式通过声明性的api将很多样板从您身上抽象出来:
CompletableFuture
.supplyAsync(() -> Try.of(() -> methodThatThrows()))
.thenAccept(res -> System.out.println(res));
或者,如果您不打算使用CompletableFuture
,则可以选择使用Future
monad进一步减少样板代码:
Future.of(() -> methodThatThrows())
.onComplete(result -> System.out.println(result));
无论哪种方式,最终得到的Future<T>
都是Try<T>
,可以是Success<T>
或Failure
都可以处理相应地。
答案 2 :(得分:0)
我并不是说这是唯一的方法,还是最有效的方法,我是在分享对我DRY
有帮助的解决方案,它可能会也可能不会为您服务。如果您有更好的解决方案,请分享。
我创建了以下实用程序方法
@Component
public class CompletableFutureUtil {
@Autowired
private SomeGenericServiceThatThrowsException genericService;
public <T> CompletableFuture<Collection<T>> fireupCompletableFutureAsynchronously(Class<T> type) {
CompletableFuture<Collection<T>> future = CompletableFuture.supplyAsync(() -> {
Collection<T> mystery = null;
try {
mystery = genericService.list(type);
} catch (SomeException e) {
e.printStackTrace();
//Handle the exception
}
return mystery;
});
return future;
}
}
现在,autowiring
之后,我可以按以下方式重用上述实用程序方法
@Autowired private CompletableFutureUtil futureUtil;
通话基本上最多变成一到两行
futureUtil.fireupCompletableFutureAsynchronously(SomePojo.class)
.thenAcceptAsync(result -> //do something with result);
futureUtil.fireupCompletableFutureAsynchronously(OtherPojo.class)
.thenAcceptAsync(result -> //do something with result);
开心的DRY+ing