让 CompletableFuture exceptionally() 处理 supplyAsync() 异常
Letting CompletableFuture exceptionally() handle a supplyAsync() Exception
问题很简单:我正在寻找一种将 CompletableFuture#exceptionally
与 CompletableFuture#supplyAsync
一起使用的优雅方式。这是行不通的:
private void doesNotCompile() {
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(() -> throwSomething())
.exceptionally(Throwable::getMessage);
}
private String throwSomething() throws Exception {
throw new Exception();
}
我认为 exceptionally()
背后的想法正是为了处理抛出 Exception
的情况。但是,如果我这样做,它就会起作用:
private void compiles() {
CompletableFuture<String> thisIsFine = CompletableFuture.supplyAsync(() -> {
try {
throwSomething();
return "";
} catch (Exception e) {
throw new RuntimeException(e);
}
}).exceptionally(Throwable::getMessage);
}
我可以使用它,但它看起来很糟糕并且让事情更难维护。有没有一种不需要将所有 Exception
转换为 RuntimeException
来保持这种清洁的方法?
这可能不是一个超级流行的库,但我们在内部使用它(有时我也在那里做一些工作;虽然次要):NoException。它真的非常非常适合我的口味。这不是它唯一拥有的东西,但绝对涵盖了您的用例:
这是一个示例:
import com.machinezoo.noexception.Exceptions;
import java.util.concurrent.CompletableFuture;
public class SO64937499 {
public static void main(String[] args) {
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(Exceptions.sneak().supplier(SO64937499::throwSomething))
.exceptionally(Throwable::getMessage);
}
private static String throwSomething() throws Exception {
throw new Exception();
}
}
或者您可以自己创建这些:
final class CheckedSupplier<T> implements Supplier<T> {
private final SupplierThatThrows<T> supplier;
CheckedSupplier(SupplierThatThrows<T> supplier) {
this.supplier = supplier;
}
@Override
public T get() {
try {
return supplier.get();
} catch (Throwable exception) {
throw new RuntimeException(exception);
}
}
}
@FunctionalInterface
interface SupplierThatThrows<T> {
T get() throws Throwable;
}
和用法:
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(new CheckedSupplier<>(SO64937499::throwSomething))
.exceptionally(Throwable::getMessage);
问题很简单:我正在寻找一种将 CompletableFuture#exceptionally
与 CompletableFuture#supplyAsync
一起使用的优雅方式。这是行不通的:
private void doesNotCompile() {
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(() -> throwSomething())
.exceptionally(Throwable::getMessage);
}
private String throwSomething() throws Exception {
throw new Exception();
}
我认为 exceptionally()
背后的想法正是为了处理抛出 Exception
的情况。但是,如果我这样做,它就会起作用:
private void compiles() {
CompletableFuture<String> thisIsFine = CompletableFuture.supplyAsync(() -> {
try {
throwSomething();
return "";
} catch (Exception e) {
throw new RuntimeException(e);
}
}).exceptionally(Throwable::getMessage);
}
我可以使用它,但它看起来很糟糕并且让事情更难维护。有没有一种不需要将所有 Exception
转换为 RuntimeException
来保持这种清洁的方法?
这可能不是一个超级流行的库,但我们在内部使用它(有时我也在那里做一些工作;虽然次要):NoException。它真的非常非常适合我的口味。这不是它唯一拥有的东西,但绝对涵盖了您的用例:
这是一个示例:
import com.machinezoo.noexception.Exceptions;
import java.util.concurrent.CompletableFuture;
public class SO64937499 {
public static void main(String[] args) {
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(Exceptions.sneak().supplier(SO64937499::throwSomething))
.exceptionally(Throwable::getMessage);
}
private static String throwSomething() throws Exception {
throw new Exception();
}
}
或者您可以自己创建这些:
final class CheckedSupplier<T> implements Supplier<T> {
private final SupplierThatThrows<T> supplier;
CheckedSupplier(SupplierThatThrows<T> supplier) {
this.supplier = supplier;
}
@Override
public T get() {
try {
return supplier.get();
} catch (Throwable exception) {
throw new RuntimeException(exception);
}
}
}
@FunctionalInterface
interface SupplierThatThrows<T> {
T get() throws Throwable;
}
和用法:
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(new CheckedSupplier<>(SO64937499::throwSomething))
.exceptionally(Throwable::getMessage);