简体   繁体   English

当flatMap返回一个空的Mono时如何调用switchIfEmpty?

[英]How to call switchIfEmpty when the flatMap returns an empty Mono?

My title sounds confusing so let me explain with some imperative pseudo code for what I'm trying to do我的标题听起来令人困惑,所以让我用一些命令式伪代码来解释我正在尝试做的事情

Mono<Void> func() {
  Mono<MyThing> myThing = getMyThing();
  if myThing is not empty:
    return doSomething();
  else:
    return doSomethingElse();
}

Here's where I'm stuck when I try to do this reactively:当我尝试被动地执行此操作时,这就是我卡住的地方:

Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
  Mono<MyThing> myThing = getMyThing();
  return myThing
    .flatMap(thing -> {
      Mono<Void> somethingMono = doSomething();
      return somethingMono;
    })
    .switchIfEmpty(Mono.defer(() -> {
      Mono<Void> somethingElseMono = doSomethingElse();
      return somethingElseMono;
    });
}

This works fine when myThing is empty.myThing为空时,这可以正常工作。 It skips the .flatMap() and executes the .switchIfEmpty() statement.它跳过.flatMap()并执行.switchIfEmpty()语句。

However, when myThing is not empty, it executes .flatMap() which is what I want.但是,当myThing不为空时,它会执行我想要的.flatMap() But the flatMap returns a Mono<Void> which triggers the subsequent .switchIfEmpty() method.但是 flatMap 返回一个触发后续.switchIfEmpty()方法的Mono<Void>

I tried swapping the position of the .flatMap() and .switchIfEmpty() but that doesn't work either because the .switchIfEmpty() returns a Mono<Void> whereas the .flatMap() expects a Mono<MyThing> .我尝试交换.flatMap().switchIfEmpty()的 position 但这也不起作用,因为.switchIfEmpty()返回Mono<Void>.flatMap()需要Mono<MyThing>

This seems like a common pattern so wondering what's the right way to do this.这似乎是一种常见的模式,所以想知道这样做的正确方法是什么。

There's a few ways you could do this.有几种方法可以做到这一点。 Since you're using Mono<Void> as the return type, you could do something like:由于您使用Mono<Void>作为返回类型,您可以执行以下操作:

getMyThing()
        .delayUntil(thing -> doSomething())
        .switchIfEmpty(doSomethingElse().cast(String.class))
        .then()

...but that's not the neatest or clearest IMHO. ...但这不是最整洁或最清晰的恕我直言。 It's a bit more verbose, but I'd be tempted to map to an optional as so:它有点冗长,但我很想把 map 变成一个可选的:

getMyThing().map(Optional::of).defaultIfEmpty(Optional.empty())
        .flatMap(thing -> thing.isPresent() ? doSomething() : doSomethingElse())
        .then()

If you need to do this often, you might consider a transformation utility method:如果您需要经常这样做,您可以考虑使用转换实用程序方法:

public static <T> Mono<Optional<T>> optional(Mono<T> mono) {
    return mono.map(Optional::of).defaultIfEmpty(Optional.empty());
}

...which would then enable you to just do getMyThing().transform(Utils::optional) rather than do the explicit mapping / default each time. ...这将使您只需执行getMyThing().transform(Utils::optional)而不是每次都执行显式映射/默认值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM