我接手了一个使用Spring和相关库,包括Reactor编写的Java REST服务。对于像REST调用或数据库操作这样的昂贵操作,代码在很大程度上将结果封装到Reactor Mono中。
代码中需要处理各种问题,但其中一个问题是嵌套Mono
的flatMap
,用于执行一系列昂贵的操作,导致缩进几个级别,变成难以阅读的混乱。我发现这特别令人恼火,因为我之前从Scala过来,那里使用flatMap
的方式不会像这样糟糕,因为for推导式语法糖可以使所有内容保持大致相同的作用域而不会变得更深。
目前为止,我还没有找到一种方法来解决这个问题,使其更易读,除了进行大规模重构(即使在这种情况下,我也不确定从何处开始进行这种重构)。
下面是基于代码的匿名示例,(所有语法错误都是匿名化引起的):
public Mono<OutputData> userActivation(InputData input) {
Mono<DataType1> d1 = service.expensiveOp1(input);
Mono<OutputData> result =
d1
.flatMap(
d1 -> {
return service
.expensiveOp2(d1.foo())
.flatMap(
d2 -> {
if (Status.ACTIVE.equals(d2.getStatus())) {
throw new ConflictException("Already active");
}
return service
.expensiveOp3(d1.bar(), d2.baz())
.flatMap(
d3 -> {
d2.setStatus(Status.ACTIVE);
return service
.expensiveOp5(d1, d2, d3)
.flatMap(
d4 -> {
return service.expensiveOp6(d1, d4.foobar())
});
});
});
})
return result;
}
PreProcessedRecord
、ProcessedRecord
和AuditedRecord
作为类,以及preProcess
、process
和audit
作为方法名称。至于适合的命名,因人而异! - Michael BerryMono ultVal = Mono.create(callback -> { myCallback.apply(someData).flatMap(d -> req.getBodyAsString().flatMap(d1 -> { callback.success(resp); return Mono.just(d); }));
我试图将回调链接到事件循环中,并且无法控制“req.getBodyAsString()”。 - Jeremy Reed