使用CompletableFuture
的想法是因爲它提供了一個鏈,而前幾個步驟在最後一步使用它之前封裝了bean。因爲在這些步驟中可能會發生任何異常,並且使用exceptionally
來處理錯誤。但是,exceptionally
只接受Throwable
參數,到目前爲止我還沒有找到一種方法來獲取這些封裝的bean。CompletableFuture異常破壞工作鏈
CompletableFuture.supplyAsync(this::msgSource)
.thenApply(this::sendMsg).exceptionally(this::errorHandler).thenAccept(this::saveResult)
public List<Msg> msgSource() // take message from somewhere.
public List<Msg> sendMsg(List<Msg>) // exceptions may happen like 403 or timeout
public List<Msg> errorHandler() // set a success flag to false in Msg.
public void saveResult(List<Msg>) // save send result like success or false in data center.
在上面的例子中,註釋是工作流程。但是,由於errorHandler
既不接受List<Msg>
也不傳遞它,所以鏈被破壞。如何從msgSource
獲得回報?
EDIT
public class CompletableFutureTest {
private static Logger log = LoggerFactory.getLogger(CompletableFutureTest.class);
public static void main(String[] args) {
CompletableFutureTest test = new CompletableFutureTest();
CompletableFuture future = new CompletableFuture();
future.supplyAsync(test::msgSource)
.thenApply(test::sendMsg).exceptionally(throwable -> {
List<String> list = (List<String>) future.join(); // never complete
return list;
}).thenAccept(test::saveResult);
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
private List<String> saveResult(List<String> list) {
return list;
}
private List<String> sendMsg(List<String> list) {
throw new RuntimeException();
}
public List<String> msgSource() {
List<String> result = new ArrayList<>();
result.add("1");
result.add("2");
return result;
}
}
不會爲所有的'Msg'設置'success = false'如果一個失敗? – Eugene
@Eugene:當然。如果'sendMsg(列表)'失敗,則意味着整個列表失敗。這就是問題代碼的設計方式,它適用於'CompletableFuture'的使用,以及接收和返回'List'的方法。 –
Holger
如果'異常地'忘記了它以前的作品在消息中所做的所有操作,那麼它的返回將是無用的。但是你的第一個代碼段表明,有一種方法可以將前一項工作確實拿出來,只是前提條件是一個*知道哪些工作會導致異常*。我認爲是得到了引發異常的函數的參數(在本例中爲'List')。有時候,這個鏈條可能會更長,嘗試捕捉它們中的每一個都可能是毫無意義的。 –
Tiina