IT

Mono switch If Empty()는 항상 호출됩니다.

itgroup 2023. 2. 27. 22:52
반응형

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

반응형