You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webflux控制流场景:应使用then还是flatMap?

When to Use then() vs flatMap() for Reactor Existence Check Flow

Great question! Let's break down which operator makes sense for your WebFlux control flow scenario, where you need to validate an object exists before running business logic (and throw an error if it doesn't).

First, let's recap your core requirement:

Check if an object exists via repository.exists(Mono<IdType>). If it does, run someBusinessLogic(). If not, throw a DoesntExistException.

Understanding then() for Your Scenario

Your current code uses then() after the existence check, and this is actually the more semantically correct choice here. Here's why:

  • then() ignores all upstream elements and only reacts to the completion signal of the preceding Mono. It says: "Once the previous step finishes successfully (without errors), run the next Mono."
  • In your flow, the existence check is a pure validation step—you don't need to pass any data (like the IdType or the Boolean result from exists()) to your business logic. You just need to ensure the validation passes (i.e., the object exists, so no exception is thrown).

Your code structure is clean because it separates the validation phase from the business logic phase:

public Mono<Void> handleObjectWithSomeId(Mono<IdType> id){
 return id.flatMap(repository::exists) // Check if object exists
          .flatMap(e -> e ? Mono.empty() : Mono.error(new DoesntExistException())) // Validate existence, throw if missing
          .then( // Run business logic ONLY after validation completes successfully
              Mono.fromCallable(this::someBusinessLogic)
          );
}

When Would flatMap() Be Better?

flatMap() is designed to transform upstream elements into new Publishers. It's useful when you need to use the output of the previous step to drive the next part of your flow.

For your scenario, a flatMap-based approach would look something like this:

public Mono<Void> handleObjectWithSomeId(Mono<IdType> id){
 return id.flatMap(repository::exists)
          .flatMap(exists -> {
              if (exists) {
                  return Mono.fromCallable(this::someBusinessLogic); // Use existence result to trigger logic
              } else {
                  return Mono.error(new DoesntExistException());
              }
          })
          .then(); // Convert to Mono<Void> if needed
}

But this is less ideal here because:

  • You're not actually using the exists Boolean value for anything beyond the basic check—you don't need to pass it to the business logic.
  • The code mixes validation and business logic in the same flatMap() block, making it slightly less readable than separating them with then().

Final Recommendation

Use then() for your specific scenario:

  • It makes your code's intent clearer: "First validate the object exists, then run the business logic."
  • It keeps validation and business logic separate, which improves maintainability.
  • It's more idiomatic for Reactor flows where you don't need to propagate upstream data to the next step.

Only use flatMap() if you later need to leverage the output of the existence check (or the original IdType) within your business logic.

内容的提问来源于stack exchange,提问作者Filip Malczak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:51:17