[英]Use flatMap after method returning Mono<Void>
我对 Project Reactor 的某些方面的理解感到困惑。
我有以下组件列表:
Mono<Void>
或Mono.error()
Mono<Item>
Mono<Void
业务逻辑非常简单:验证参数 (1)、将项目保存到数据库 (2) 和记录操作 (3)。 问题是验证器 (1) 如果输入数据没有错误,则返回Mono.empty()
Mono.error()
如果输入参数包含一些错误,则返回 Mono.error()。
我想实现以下目标:
Mono.empty()
则继续链Mono.error()
则立即停止处理并抛出将由exceptionHanlder
处理的错误我尝试了两种选择:
验证后首先使用.then(Mono<Item> item)
。 它允许我在验证后执行保存操作。 鉴于.then()
忽略任何错误,我不能引发异常。
return inputValidator.validateFields(userId, projectId)
.then(repository.save(item))
.onErrorMap(RepoException.class, ex -> new UnexpectedError("Failed to save item", ex))
.subscribeOn(Schedulers.boundedElastic())
.doOnSuccess(n -> logService.logActivity(new Activity(adminId, n))
.subscribe());
第二个是.flatMap(Function<Mono<Void>, <Mono<? extends Item> func)
验证后。 这种方法可能会引发验证器异常,但我无法执行保存操作,因为flatMap()
不会触发空结果。
return inputValidator.validateFields(userId, projectId)
.flatMap(v -> repository.save(item))
.onErrorMap(RepoException.class, ex -> new UnexpectedError("Failed to save item", ex))
.subscribeOn(Schedulers.boundedElastic())
.doOnSuccess(n -> logService.logActivity(new Activity(adminId, n))
.subscribe());
在保存(步骤 2)后访问创建的对象也很重要,因为我需要将它传递给记录器服务。
您不能使用flatMap
因为没有onNext
信号 - 使用then
代替。 不知道“被调用”是什么意思,但反应中的装配时间和订阅时间之间存在差异。 如果inputValidator.validateFields
返回onError
信号,您在then
中指定的发布者将不会被解析。
这是验证失败的测试,您可能会看到未触发订阅
@Test
void saveWasNotCalledIfValidationFailed() {
var saveMock = PublisherProbe.of(Mono.just("id"));
var repo = mock(Repository.class);
when(repo.save())
.thenReturn(saveMock.mono());
var res = validateFields()
.then(repo.save())
.onErrorMap(IllegalArgumentException.class,
ex -> new IllegalStateException("Failed to save item", ex)
);
StepVerifier.create(res)
.expectError(IllegalStateException.class)
.verify();
saveMock.assertWasNotSubscribed();
}
private Mono<Void> validateFields() {
return Mono.error(new IllegalArgumentException("oops"));
}
public static class Repository {
public Mono<String> save() {
return Mono.just("id");
}
}
这是通过验证的测试
@Test
void saveIsCalledIfValidationPassed() {
var saveMock = PublisherProbe.of(Mono.just("id"));
var repo = mock(Repository.class);
when(repo.save())
.thenReturn(saveMock.mono());
var res = validateFields()
.then(repo.save())
.onErrorMap(IllegalArgumentException.class,
ex -> new IllegalStateException("Failed to save item", ex)
);
StepVerifier.create(res)
.expectNext("id")
.verifyComplete();
saveMock.assertWasSubscribed();
}
private Mono<Void> validateFields() {
return Mono.empty();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.