[英]Reactive Java Mono.zip with Mono.empty() parameters
Using Spring with Reactor Project to zip multiple api calls as aggregated result.使用 Spring 和 Reactor 项目将多个 api 调用压缩为聚合结果。 Can Mono.zip() with Mono.empty() parameters return null result?
Mono.zip() 和 Mono.empty() 参数可以返回空结果吗?
Mono<Dog> dogMono = dogApiClient.getDog(); // can return Mono.empty()
Mono<Cat> catMono = catMono = catApiClient.getCat(); // can returnMono.empty()
Mono<Horse> horseMono = horseApiClient.getHorse(); // can return Mono.empty()
Mono.zip(dogMono, dogMobo, horseMono)
.map(this::mapToAnimals);
Expected result:预期结果:
{
dog: null, // if dog is null
cat: null, // if cat is null
horse: null, // if horse is null
}
Actual result:实际结果:
{
dog: {
name: null,
surname: null
},
cat: {
name: null,
surname: null
},
horse: {
name: null,
surname: null
}
}
or或者
"" // empty
Well, it's certainly not an elegant solution, but you can choose to wrap your values inside Optional:好吧,这当然不是一个优雅的解决方案,但您可以选择将您的值包装在 Optional 中:
Mono<Optional<Dog>> dogMono = Mono.just(Optional.empty());
if(condition1) {
dogMono = dogApiClient.getDog().map(Optional::of);
}
Mono<Optional<Cat>> catMono = Mono.just(Optional.empty());
if(condition2) {
catMono = catApiClient.getCat().map(Optional::of);
}
Mono<Optional<Horse>> horseMono = Mono.just(Optional.empty());
if(condition3) {
horseMono = horseApiClient.getHorse().map(Optional::of);
}
Mono.zip(dogMono, catMono, horseMono)
.map(this::mapToAnimals);
private Output mapToAnimals(Tuple3<Optional<Dog>, Optional<Cat>, Optional<Horse>> tuple3)
{
Dog dog = tuple3.getT1().orElse(null);
Cat cat = tuple3.getT2().orElse(null);
Horse horse = tuple3.getT3().orElse(null);
return new Output(dog, cat, horse);
}
In Reactive Streams, the null
value is forbidden.在 Reactive Streams 中,
null
值是被禁止的。 Furthermore, zip
expect that all combined publishers have the same number of elements.此外,
zip
期望所有合并的发布者具有相同数量的元素。 Or to put it differently: it short-circuits as soon as one of the publishers completes.或者换一种说法:一旦其中一个出版商完成,它就会短路。
So if you use Mono.empty()
, that Mono
completes immediately and triggers the zip
to complete empty as well.因此,如果您使用
Mono.empty()
,则Mono
立即完成并触发zip
以完成清空。
One possible solution would be to have a "null object" instance of each animal, like this:一种可能的解决方案是为每个动物创建一个“空对象”实例,如下所示:
public static final Dog NO_DOG = new Dog(...);
public static final Cat NO_CAT = new Cat(...);
public static final Horse NO_HORSE = new Horse(...);
Mono<Dog> dogMono = (condition1) ? Mono.just(dogApliClient.getDog()) : Mono.just(NO_DOG);
Mono<Cat> catMono = (condition2) ? Mono.just(catApliClient.getCat()) : Mono.just(NO_CAT);
Mono<Horse> horseMono = (condition3) ? Mono.just(horseApliClient.getHorse()) : Mono.just(NO_HORSE);
Mono.zip(dogMono, catMono, horseMono)
.map(Animals::fromDogCatAndHorse);
Map<String, Object> fromDogCatAndHorse(Tuple3<Dog, Cat, Horse> tuple) {
Map<String, Object> forJson = new HashMap<>(3);
Dog dog = tuple.getT1();
if (dog = NO_DOG) json.put("dog", null); else json.put("dog", dog);
Cat cat = tuple.getT2();
if (cat = NO_CAT) json.put("cat", null); else json.put("cat", cat);
Horse horse = tuple.getT3();
if (horse = NO_HORSE) json.put("horse", null); else json.put("horse", horse);
return forJson;
}
If you can't define these null object instances, then the solution from @yossarian would work too.如果您无法定义这些空对象实例,那么@yossarian 的解决方案也可以。
Note that there's still a big issue with the api client calls, though : the Mono.just(apiClient.blockingCall())
pattern.请注意,api 客户端调用仍然存在一个大问题:
Mono.just(apiClient.blockingCall())
模式。
Here you're essentially shoehorning a blocking call inside what is supposed to be a non-blocking controller...在这里,您实际上是在应该是非阻塞控制器的内部硬塞进一个阻塞调用......
Ideally these clients would return a Mono<Dog|Cat|Horse>
to reflect a non-blocking nature.理想情况下,这些客户端将返回
Mono<Dog|Cat|Horse>
以反映非阻塞性质。 As an example, with a proper non-blocking API, dogMono
can be initialized like this:例如,使用适当的非阻塞 API,可以像这样初始化
dogMono
:
Mono<Dog> dogMono = (condition1) ? dogApiClient.getDogAsync() : Mono.just(NO_DOG);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.