У меня есть цепочка ListenableFutures, где выход предыдущего является входом следующего. Я сталкиваюсь с тем, что в некоторых особых случаях мы можем получить результат на ранней стадии процесса. Код выглядит примерно следующим образом (но имеет гораздо больше параметров, локальных переменных, вызовов вспомогательных методов и т. Д. c.):
public ListenableFuture<R> result(I input) {
if (specialCase(input)) {
return Futures.immedateFuture(specialResult(input));
}
ListenableFuture<A> futureA = getA(input);
return Futures.transformAsync(futureA, a -> process(a), directExecutor);
}
public ListenableFuture<R> process(A a) {
if (specialCase(a)) {
return Futures.immedateFuture(specialResult(a));
}
ListenableFuture<B> futureB = getB(a);
return Futures.transform(futureB, b -> process(b), directExecutor);
}
public R process(A b) {
if (specialCase(b)) {
return specialResult(b);
}
return finalResult(b);
}
Я хотел бы улучшить читаемость этого кода, поэтому что более очевидно, что является основным конвейером обработки (т. е. getA -> getB -> finalResult) в основной функции, без необходимости отслеживать его. Я думал как-то использовать FluentFuture , но я не знаю, как лучше всего обработать эти ранние операторы возврата.
Одна из идей, которые у меня были, - это использовать выделенное Исключение и не удалось. фьючерсы в качестве побочного канала для этих специальных результатов, но это не кажется элегантным - это правильные возвращаемые значения, а не ошибки в конце концов.