2016-05-04 2 views
3

Я понимаю, что я бы хотел, чтобы потребители нашего API не должны обрабатывать исключение. Или, возможно, более четко я хотел бы гарантировать, что исключение всегда регистрируется, но только потребитель будет знать, как справиться с успехом. Я хочу, чтобы клиент мог справиться с этим исключением, если они этого захотят, нет действительного File, чтобы я мог вернуться к ним.Отдельная обработка исключений из CompletableFuture

примечания: FileDownload является Supplier<File>

@Override 
public CompletableFuture<File> processDownload(final FileDownload fileDownload) { 
    Objects.requireNonNull(fileDownload); 
    fileDownload.setDirectory(getTmpDirectoryPath()); 
    CompletableFuture<File> future = CompletableFuture.supplyAsync(fileDownload, executorService); 
    future... throwable -> { 
     if (throwable != null) { 
      logError(throwable); 
     } 
     ... 
     return null; // client won't receive file. 
    }); 
    return future; 

} 

Я не очень понимаю CompletionStage вещей. Использую ли я exception или handle? вернуть первоначальное будущее или будущее, которое они возвратят?

+0

Что вы хотите, чтобы результат вашего будущего был, если выбрано исключение? Должен ли потребитель по-прежнему получать исключение, или вы хотите, чтобы они не знали, что произошло? – Jeffrey

+0

@Jeffrey Я бы ожидал, что они получат исключение, обработайте его сами, если захотят. Я не ожидаю, что они получат файл – xenoterracide

ответ

7

Предполагая, что вы не хотите, чтобы повлиять на результат вашего CompletableFuture, вы хотите использовать CompletableFuture::whenComplete:

future = future.whenComplete((t, ex) -> { 
    if (ex != null) { 
    logException(ex); 
    } 
}); 

Теперь, когда потребитель вашего API пытается вызвать future.get(), они получат исключение , но им необязательно что-то делать с этим.


Однако, если вы хотите сохранить потребителя неведении, за исключением (возврат null когда fileDownload терпит неудачу), вы можете использовать либо CompletableFuture::handle или CompletableFuture::exceptionally:

future = future.handle((t, ex) -> { 
    if (ex != null) { 
    logException(ex); 
    return null; 
    } else { 
    return t; 
    } 
}); 

или

future = future.exceptionally(ex -> { 
    logException(ex); 
    return null; 
}); 
+3

Это намного проще. Потребитель, не знающий об исключениях, может быть просто привязан, используя 'future.thenAccept'. Ключевым моментом здесь является то, что потребитель никогда не вызывается в исключительном случае, поэтому ему не нужно обрабатывать ни одно, ни исключение, ни значение «null». В нижней строке, не используйте 'get()' ... – Holger

Смежные вопросы