Je suis tombé sur Mono.defer () dans du code webflux Spring
J'ai recherché la méthode dans la documentation mais je ne comprends pas l'explication:
"Créer un fournisseur Mono qui fournira un Mono cible auquel s'abonner pour chaque abonné en aval"
s'il vous plaît pourrais-je avoir une explication et un exemple. Y a-t-il un endroit avec un tas d'exemples de code Reactor (leurs tests unitaires?) Que je pourrais référencer.
merci
C'est un peu une simplification excessive, mais conceptuellement, les sources du réacteur sont soit paresseuses, soit avides. Les plus avancées, comme une requête HTTP, devraient être évaluées paresseusement. De l'autre côté, les plus simples comme Mono.just
Ou Flux.fromIterable
Sont impatients.
J'entends par là que l'appel de Mono.just(System.currentTimeMillis())
invoquera immédiatement la méthode currentTimeMillis()
et capturera le résultat. Ce résultat est seulement émis par le Mono
une fois qu'il est abonné. S'abonner plusieurs fois ne change pas non plus la valeur:
Mono<Long> clock = Mono.just(System.currentTimeMillis());
//time == t0
Thread.sleep(10_000);
//time == t10
clock.block(); //we use block for demonstration purposes, returns t0
Thread.sleep(7_000);
//time == t17
clock.block(); //we re-subscribe to clock, still returns t0
L'opérateur defer
est là pour rendre cette source paresseuse, réévaluant le contenu du lambda à chaque fois qu'il y a un nouvel abonné:
Mono<Long> clock = Mono.defer(() -> Mono.just(System.currentTimeMillis()));
//time == t0
Thread.sleep(10_000);
//time == t10
clock.block(); //invoked currentTimeMillis() here and returns t10
Thread.sleep(7_000);
//time == t17
clock.block(); //invoke currentTimeMillis() once again here and returns t17
avec des mots simples si vous voyez dans la première vue, c'est comme Mono.just () mais ce n'est pas le cas. lorsque vous exécutez Mono.just (), il crée immédiatement un observable (mono) et le réutilise, mais lorsque vous utilisez le report, il ne le crée pas immédiatement, il crée un nouvel observable dans chaque abonnement.
Un cas d'utilisation pour voir la différence
int a = 5;
@Override
public void run(String... args) throws Exception {
Mono<Integer> monoJust = Mono.just(a);
Mono<Integer> monoDefer = Mono.defer(() -> Mono.just(a));
monoJust.subscribe(integer1 -> System.out.println(integer1));
monoDefer.subscribe(integer1 -> System.out.println(integer1));
a = 7;
monoJust.subscribe(integer1 -> System.out.println(integer1));
monoDefer.subscribe(integer1 -> System.out.println(integer1));
}
impression: 5,5,5,7
si vous voyez que mono.just a créé l'observable immédiatement et que cela ne change pas même si la valeur a changé, mais le report crée l'observable dans subscribe, vous travaillerez donc avec la valeur onsubscribe actuelle
J'essayais defer
pour un cas d'utilisation différent. A écrit le code ci-dessous pour vérifier et partager car cela pourrait aider les autres. Mon cas d'utilisation consistait à enchaîner deux Mono
et à m'assurer que le premier était complet avant que le second ne soit repris. Et le second contenait un appel de blocage dont le résultat est utilisé pour répondre à une réponse Mono
avec une réponse empty
ou error
. Sans defer
, mon appel de blocage est exécuté quel que soit le résultat du premier. Mais lors de l'utilisation de defer
, l'appel de blocage n'est exécuté que lorsque le premier Mono
est terminé. Code ci-dessous:
public static void main(String[] args) {
long cur = System.currentTimeMillis();
boolean succeed = true;
Mono<Integer> monoJust = Mono.create(consumer -> {
System.out.println("MonoJust inside " + (System.currentTimeMillis() - cur));
if (succeed) {
consumer.success(1);
} else {
consumer.error(new RuntimeException("aaa"));
}
});
Mono<String> monoJustStr = Mono.create(consumer -> {
System.out.println("MonoJustStr inside: " + (System.currentTimeMillis() - cur));
consumer.success("one");
});
System.out.println("##1##: Begin");
monoJust.then(evaluator() ? Mono.empty() : monoJustStr).subscribe(d -> System.out.println("##1##: "+d), e-> System.err.println(e));
System.out.println("##1##: Done: "+(System.currentTimeMillis() - cur));
System.out.println("\n\n\n##2##: Begin");
monoJust.then(Mono.defer(() -> evaluator() ? Mono.empty() : monoJustStr)).subscribe(d -> System.out.println("##2##: "+d), e-> System.err.println(e));
System.out.println("##2##: Done: " + (System.currentTimeMillis() - cur));
}
private static boolean evaluator() {
System.out.println("Inside Evaluator");
return false;
}
Sortie avec succeed=true
- Observer la séquence "Inside Evaluator" et "MonoJust inside"
##1##: Begin
Inside Evaluator
MonoJust inside 540
MonoJustStr inside: 542
##1##: one
##1##: Done: 542
##2##: Begin
MonoJust inside 544
Inside Evaluator
MonoJustStr inside: 544
##2##: one
##2##: Done: 544
Ci-dessous est sorti avec succeed = false
- Notez que l'évaluateur n'est pas appelé.
##1##: Begin
Inside Evaluator
MonoJust inside 565
Java.lang.RuntimeException: aaa
##1##: Done: 567
##2##: Begin
MonoJust inside 569
Java.lang.RuntimeException: aaa
##2##: Done: 569