Mono switch If Empty()는 항상 호출됩니다.
두 가지 방법이 있습니다.
주요 방법:
@PostMapping("/login")
public Mono<ResponseEntity<ApiResponseLogin>> loginUser(@RequestBody final LoginUser loginUser) {
return socialService.verifyAccount(loginUser)
.flatMap(socialAccountIsValid -> {
if (socialAccountIsValid) {
return this.userService.getUserByEmail(loginUser.getEmail())
.switchIfEmpty(insertUser(loginUser))
.flatMap(foundUser -> updateUser(loginUser, foundUser))
.map(savedUser -> {
String jwts = jwt.createJwts(savedUser.get_id(), savedUser.getFirstName(), "user");
return new ResponseEntity<>(HttpStatus.OK);
});
} else {
return Mono.just(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
}
});
}
이 호출된 메서드(서비스는 외부 API를 호출합니다).
public Mono<User> getUserByEmail(String email) {
UriComponentsBuilder builder = UriComponentsBuilder
.fromHttpUrl(USER_API_BASE_URI)
.queryParam("email", email);
return this.webClient.get()
.uri(builder.toUriString())
.exchange()
.flatMap(resp -> {
if (Integer.valueOf(404).equals(resp.statusCode().value())) {
return Mono.empty();
} else {
return resp.bodyToMono(User.class);
}
});
}
위의 예에서는switchIfEmpty()
항상 메인 메서드에서 호출됩니다.Mono.empty()
이 반환됩니다.
나는 이 간단한 문제에 대한 해결책을 찾을 수 없다.
다음 항목도 작동하지 않습니다.
Mono.just(null)
왜냐하면 이 방법은NullPointerException
.
또한 flatMap 메서드를 사용하여 확인할 수 없습니다.foundUser
null 입니다.
아쉽게도 platMap은 반환 시 호출이 전혀 되지 않습니다.Mono.empty()
여기에서도 조건을 추가할 수 없습니다.
@SimY4
@PostMapping("/login")
public Mono<ResponseEntity<ApiResponseLogin>> loginUser(@RequestBody final LoginUser loginUser) {
userExists = false;
return socialService.verifyAccount(loginUser)
.flatMap(socialAccountIsValid -> {
if (socialAccountIsValid) {
return this.userService.getUserByEmail(loginUser.getEmail())
.flatMap(foundUser -> {
return updateUser(loginUser, foundUser);
})
.switchIfEmpty(Mono.defer(() -> insertUser(loginUser)))
.map(savedUser -> {
String jwts = jwt.createJwts(savedUser.get_id(), savedUser.getFirstName(), "user");
return new ResponseEntity<>(HttpStatus.OK);
});
} else {
return Mono.just(new ResponseEntity<>(HttpStatus.UNAUTHORIZED));
}
});
}
switchIfEmpty가 Mono의 "값별"을 받아들이기 때문입니다.즉, 모노에 가입하기 전부터 이 대체 모노의 평가는 이미 트리거되어 있습니다.
다음과 같은 방법을 상상해 보십시오.
Mono<String> asyncAlternative() {
return Mono.fromFuture(CompletableFuture.supplyAsync(() -> {
System.out.println("Hi there");
return "Alternative";
}));
}
코드를 다음과 같이 정의할 경우:
Mono<String> result = Mono.just("Some payload").switchIfEmpty(asyncAlternative());
하천을 건설하는 동안 어떤 일이 있어도 항상 다른 선택을 하게 될 거야.이 문제를 해결하려면 다음을 사용하여 두 번째 모노의 평가를 연기할 수 있습니다.Mono.defer
Mono<String> result = Mono.just("Some payload")
.switchIfEmpty(Mono.defer(() -> asyncAlternative()));
이렇게 하면 대체 항목이 요청되었을 때만 "안녕하세요"라고 인쇄됩니다.
업데이트:
내 대답에 대해 좀 더 자세히 설명할게.현재 직면하고 있는 문제는 Reactor가 아니라 Java 언어 자체 및 메서드 매개 변수를 해결하는 방법과 관련이 있습니다.먼저 제공한 예에서 코드를 살펴봅시다.
Mono<String> result = Mono.just("Some payload").switchIfEmpty(asyncAlternative());
이것은 다음과 같이 고쳐 쓸 수 있습니다.
Mono<String> firstMono = Mono.just("Some payload");
Mono<String> alternativeMono = asyncAlternative();
Mono<String> result = firstMono.switchIfEmpty(alternativeMono);
이들 2개의 코드 스니펫은 의미상 동등합니다.포장을 계속 풀면 문제가 어디에 있는지 알 수 있습니다.
Mono<String> firstMono = Mono.just("Some payload");
CompletableFuture<String> alternativePromise = CompletableFuture.supplyAsync(() -> {
System.out.println("Hi there");
return "Alternative";
}); // future computation already tiggered
Mono<String> alternativeMono = Mono.fromFuture(alternativePromise);
Mono<String> result = firstMono.switchIfEmpty(alternativeMono);
보시다시피 미래의 연산은 우리가 작곡을 시작하는 시점에 이미 트리거되었습니다.Mono
불필요한 연산을 방지하기 위해 미래를 잘못된 평가로 포장할 수 있습니다.
Mono<String> result = Mono.just("Some payload")
.switchIfEmpty(Mono.defer(() -> asyncAlternative()));
그 포장이 풀려서
Mono<String> firstMono = Mono.just("Some payload");
Mono<String> alternativeMono = Mono.defer(() -> Mono.fromFuture(CompletableFuture.supplyAsync(() -> {
System.out.println("Hi there");
return "Alternative";
}))); // future computation defered
Mono<String> result = firstMono.switchIfEmpty(alternativeMono);
두 번째 예에서는 미래는 게으른 공급업체에 갇혀 있으며, 요청이 있을 때만 실행되도록 예약되어 있습니다.
업데이트: 2022:
일부 시간 프로젝트 원자로는 열심히 계산된 미래를 포장하기 위한 대체 API와 함께 제공되며, 이는 게으른 공급업체에서 열심히 계산하기 위한 결과를 낳는다:
Mono<String> result = Mono.just("Some payload")
.switchIfEmpty(Mono.fromCompletionStage(() -> alternativePromise()));
투표가 잘 된 답변에도 불구하고 왜 그런 행동을 하는지 아직도 이해하지 못하는 사람들을 위해:
리액터 소스(Mono).xxx 및 Flux.xxx)는 다음 중 하나입니다.
Lazily evaluated : 송신원의 내용이 평가/트리거되는 것은 서브스크라이버가 서브스크라이버에 가입했을 경우뿐입니다.
or hergy evaluated :송신원 내용은 서브스크라이버가 가입하기 전부터 즉시 평가됩니다.
express음음음 express express express express express Mono.just(xxx)
,Flux.just(xxx)
,Flux.fromIterable(x,y,z)
심이이다
「」를 사용해 .defer()
소스를 게으르게 평가하도록 강요합니다.그래서 통용되는 답변이 효과가 있는 거죠.
이렇게 하면:
someMethodReturningAMono()
.switchIfEmpty(buildError());
buildError()
대체 Mono를 작성하기 위해 열성적인 소스를 사용하는 경우 항상 제품 사용 전에 평가됩니다.
Mono<String> buildError(){
return Mono.just("An error occured!"); //<-- evaluated as soon as read
}
이것을 방지하려면 , 다음의 순서에 따릅니다.
someMethodReturningAMono()
.switchIfEmpty(Mono.defer(() -> buildError()));
자세한 내용은 이 답변을 참조하십시오.
언급URL : https://stackoverflow.com/questions/54373920/mono-switchifempty-is-always-called
'IT' 카테고리의 다른 글
제약 조건 변경 방법 (0) | 2023.02.27 |
---|---|
getDerivedStateFromProps가 setState 뒤에 호출되는 이유는 무엇입니까? (0) | 2023.02.27 |
::: 의 각도란JS (0) | 2023.02.27 |
파일에서 JSON 읽기 및 쓰기 PHP (0) | 2023.02.27 |
eslint의 이 'react/no-un-escape-Entitie' 위반을 어떻게 해결할 것인가? (0) | 2023.02.27 |