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 메서드를 사용하여 확인할 수 없습니다.foundUsernull 입니다.
아쉽게도 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 |