Spring Reactive - повторно использовать значение Mono - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть последовательность Mono преобразований с использованием flatMap.Мне удалось упростить мой производственный код до этого контрольного примера:

@Test
public void test() {
    AtomicInteger iCounter = new AtomicInteger(1);
    Mono<String> iValueMono = Mono.fromSupplier(() -> {
        int iValue = iCounter.getAndIncrement();
        System.out.println("iValueMono CALL: " + iValue);
        return String.valueOf(iValue);
    });

    Mono<String> resultMono = Mono.just("X")
            .flatMap(append(iValueMono))
            .flatMap(append(iValueMono));

    StepVerifier.create(resultMono)
            .consumeNextWith(result -> assertThat(result).isEqualTo("X11"))
            .expectComplete()
            .verify();
}

private Function<String, Mono<String>> append(Mono<String> sMono) {
    return s -> sMono.map(v -> s + v);
}

Это печатает:

iValueMono CALL: 1
iValueMono CALL: 2

org.junit.ComparisonFailure: 
Expected :"X11"
Actual   :"X12"

Я подумал - теперь я вижу, что это неправильно - что каждый раз, когда я отображаюiValueMono в вызове append() поставщик выполняется повторно для получения нового значения.Я не могу изменить в производственном коде, как реализован iValueMono (например, чтобы сохранить состояние для сохранения значения).Как я могу реализовать это так, чтобы поставщик значений вызывался только один раз, и я получал конечный результат «X11»?

Конечно, меня интересует неблокирующий, реактивный способ сделать это.

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Использование Mono.cache() является ответом:

Превратите этот моно в горячий источник и сохраните последние испущенные сигналы для дальнейшего подписчика.

Используя его:

Mono<String> iValueMono = Mono.fromSupplier(() -> {
    int iValue = iCounter.getAndIncrement();
    System.out.println("iValueMono CALL: " + iValue);
    return String.valueOf(iValue);
}).cache();

обеспечивает желаемый результат вызова поставщика только один раз.

0 голосов
/ 26 сентября 2018

Я переписал ваш тест, и теперь iValueMono выполняется только один раз, когда кажется:

@Test
public void test() {
    AtomicInteger iCounter = new AtomicInteger(0);
    Mono<String> iValueMono = getMono(iCounter.incrementAndGet());

    Mono<String> resultMono = Mono.just("X")
        .flatMap(append(iValueMono))
        .flatMap(append(iValueMono));

    StepVerifier.create(resultMono)
        .consumeNextWith(result -> assertEquals(result, "X11"))
        .expectComplete()
        .verify();
}

private Mono<String> getMono(int x) {
    System.out.println("Called");
    return Mono.just(String.valueOf(x));
}

Что вы думаете об этом?Это помогает?

...