Reactor - 如果它没有通过过滤器,如何使用 filterWhen 并仍然传递用于记录目的的值?

Reactor - How to use filterWhen and still pass the value for logging purposes if it doesn't pass the filter?

我正在尝试找出执行以下操作的正确方法。

现在,代码结构如下所示。

private fun checkExistingData(name: String): Mono<QueryResponse> {
  return repo.getDataByName(name)
    .filterWhen { Mono.just(!it.hasItems()) }
    .switchIfEmpty {
      // log the existing id and name from QueryResponse
      Mono.error(SomeCustomException))
    }
    .flatMap {
      // proceed
    }
}

如您所见,如果我想在 switchIfEmpty 子句中记录 id,我需要在其中执行 repo.getDataByName(name) 才能检索该项目,并且获取项目的 id。显然,这是低效的,因为我在 switchIfEmpty.

之前已经这样做了

正确的做法是什么?

等待有关 QueryResponse API 的更多信息,我将假设一些事情: - getDataByName returns 一个 Mono<QueryResponse>。这个 Mono 总是有价值的,即它总是发出一个 QueryResponse 无论是否可以找到数据 - QueryResponse#items 是我将在示例中用来正确访问行的内容。我还将假设它 returns a Flux<Item>

首先,filterWhen 在这里没有用,因为我们还有一个 filter(boolean) 方法。我认为反向过滤逻辑可能有点难以理解。

为什么不执行 flatMap 中的所有操作?

private fun checkExistingData(name: String): Mono<QueryResponse> {
  return repo.getDataByName(name)
    .flatMap {
       if (it.hasItems())
         it.items()
           .single()
           .doOnNext(existing -> logExisting(existing.id(), existing.name())
           .then(Mono.error(SomeCustomException)
        else
          proceed()
    }   
}

如果你第一次调用 repo.getDataByName returns a Mono 而这个 Mono 是空的,那么你不需要过滤这种情况,因为剩下的管道的将不会被调用。所以我认为你可以保留 switchIfEmpty() 来记录这个特殊情况,然后继续你的管道 flatMap():

private fun checkExistingData(name: String): Mono<QueryResponse> {
  return repo.getDataByName(name)
    .switchIfEmpty {
      // log the existing id and name from QueryResponse
      Mono.error(SomeCustomException))
    }
    .flatMap {
      // proceed
    }
}