#java #java-8 #future #completable-future
#java #java-8 #будущее #завершаемый-будущее
Вопрос:
У меня есть серия thenCompose
вызовов, похожих на
myObject.updateDB(payload)
.thenCompose(__ -> getUserID(payload.ID()))
.thenCompose(id -> getProfile(id))
.thenCompose(userProfile -> updateSomething(userProfile))
.thenCompose(__ -> notifyUser(id))
.thenAccept(__ -> doSomething())
.exceptionally(t -> doSomethingElse());
getUserID
Вызов возвращает a CompletionStage<String>
, который я использую в следующем вызове getProfile
. Мне нужно то же id
самое снова для notifyUser
вызова. Как сделать его доступным там? IDE показывает
Не удается разрешить идентификатор символа.
Ответ №1:
Проблема с вашим текущим кодом заключается в том, что к тому времени, когда вы достигнете .thenCompose(__ -> notifyUser(id))
, переменная id
больше не находится в области видимости.
Простым решением в этом случае было бы вызвать multiple thenCompose
непосредственно для CompletionStage
возвращаемого getProfile
:
myObject.updateDB(payload)
.thenCompose(__ -> getUserID(payload.ID()))
.thenCompose(id ->
getProfile(id)
.thenCompose(userProfile -> updateSomething(userProfile))
.thenCompose(__ -> notifyUser(id))
)
// rest of chain calls
Комментарии:
1. Это не простое решение. Простым решением было бы превратить эту
compose
общую цепочку в один блок кода. Нет никакой пользы в выражении этой полностью линейной последовательности на стольких этапах. Записывая его как одно действие, все необходимые значения находятся в области видимости, а также все эти неиспользуемые параметры исчезают…
Ответ №2:
Я думаю, ваш код становится проще, если вы не настаиваете на использовании thenCompose
для каждого шага:
myObject.updateDB(payload)
.thenCompose(__ -> getUserID(payload.ID()))
.thenAccept(id -> {
updateSomething(getProfile(id).join());
notifyUser(id);
})
.thenRun(() -> doSomething())
.exceptionally(t -> doSomethingElse());
Если вам требуется эффективная последовательность каждого шага, вы можете просто использовать join
:
myObject.updateDB(payload)
.thenCompose(__ -> getUserID(payload.ID()))
.thenAccept(id -> {
updateSomething(getProfile(id).join()).join();
notifyUser(id).join();
})
.thenRun(() -> doSomething())
.exceptionally(t -> doSomethingElse());
Учитывая, что вся цепочка эффективно последовательна, вы можете просто написать ее прямолинейно:
myObject.updateDB(payload)
.thenRun(() -> {
YourUserIDType id = getUserID(payload.ID()).join();
updateSomething(getProfile(id).join()).join();
notifyUser(id).join();
doSomething();
})
.exceptionally(t -> doSomethingElse());