Project Reactor:有条件地实现映射输入Mono
Project Reactor: achieving mapping input Mono conditionally
我正在尝试实现以下简单的命令式逻辑:
boolean saveImperative(final List list) {
final String existingList = readByNameImperative(list.getName());
if (Objects.isNull(existingList)) {
templateSaveImperative(existingList);
return true;
} else {
templateSaveImperative(existingList);
return false;
}
}
以声明方式使用 Project Reactor,这是我能够实现的:
@Test
public void testDeclarative() {
final Mono<List> list = createList("foo");
final Boolean result = save(list).block();
System.out.println(result);
}
private Mono<Boolean> save(final Mono<List> listMono) {
final Mono<List> existingListMono = listMono.cache()
.flatMap(list -> readByName(list.getName()));
// if
final Mono<List> savedListMono = existingListMono
.flatMap(existingList -> templateSave(Mono.just(existingList)));
final Mono<Boolean> trueResult = savedListMono.map(x -> true);
// else
return trueResult.switchIfEmpty(templateSave(existingListMono).map(x -> false));
}
private Mono<List> templateSave(final Mono<List> listMono) {
return listMono.map(list -> {
System.out.println("templateSave has been called");
return list;
});
}
private Mono<List> readByName(final String listName) {
if (listName != "list001") {
return Mono.empty();
}
return createList(listName);
}
private Mono<List> createList(final String name) {
final List list = List.builder().name(name).build();
return Mono.just(list);
}
@Value
@Builder
private static class List {
private final String name;
}
如果我用 list001
执行测试,它会打印:
templateSave has been called
true
符合预期,但如果我用 foo
调用它,那么我得到
null
我会错过什么?我希望输出如下:
templateSave has been called
false
在那种情况下。
final Mono<List> existingListMono = listMono.cache()
.flatMap(list -> readByName(list.getName()));
...在您的保存方法中,将获取您现有的列表并使用 readByName()
.
对其进行平面映射
您的 readByName()
方法如下:
private Mono<List> readByName(final String listName) {
if (listName != "list001") {
return Mono.empty();
}
return createList(listName);
}
(我认为这与此问题无关,但 don't use == or != for comparing strings。)
由于您的 listName
是 foo
,而不是 list001
,它 return 是一个空的 Mono
- 因此 existingListMono
变成了一个空的单声道,并暗示 savedListMono
和 trueResult
.
然而,当您调用 switchIfEmpty()
语句时,您传入了 templateSave(existingListMono)
- 由于 existingListMono
如上所述是一个空的 Mono
,因此 save()
方法 returns 一个空 Mono
.
...当你阻塞一个空的 Mono
时你会得到 null - 因此结果。
因此,您可能希望在 save()
方法的 return 语句中使用 listMono
而不是 existingListMono
,这将为您提供结果再之后:
trueResult.switchIfEmpty(templateSave(listMono).map(x -> false))
我正在尝试实现以下简单的命令式逻辑:
boolean saveImperative(final List list) {
final String existingList = readByNameImperative(list.getName());
if (Objects.isNull(existingList)) {
templateSaveImperative(existingList);
return true;
} else {
templateSaveImperative(existingList);
return false;
}
}
以声明方式使用 Project Reactor,这是我能够实现的:
@Test
public void testDeclarative() {
final Mono<List> list = createList("foo");
final Boolean result = save(list).block();
System.out.println(result);
}
private Mono<Boolean> save(final Mono<List> listMono) {
final Mono<List> existingListMono = listMono.cache()
.flatMap(list -> readByName(list.getName()));
// if
final Mono<List> savedListMono = existingListMono
.flatMap(existingList -> templateSave(Mono.just(existingList)));
final Mono<Boolean> trueResult = savedListMono.map(x -> true);
// else
return trueResult.switchIfEmpty(templateSave(existingListMono).map(x -> false));
}
private Mono<List> templateSave(final Mono<List> listMono) {
return listMono.map(list -> {
System.out.println("templateSave has been called");
return list;
});
}
private Mono<List> readByName(final String listName) {
if (listName != "list001") {
return Mono.empty();
}
return createList(listName);
}
private Mono<List> createList(final String name) {
final List list = List.builder().name(name).build();
return Mono.just(list);
}
@Value
@Builder
private static class List {
private final String name;
}
如果我用 list001
执行测试,它会打印:
templateSave has been called
true
符合预期,但如果我用 foo
调用它,那么我得到
null
我会错过什么?我希望输出如下:
templateSave has been called
false
在那种情况下。
final Mono<List> existingListMono = listMono.cache()
.flatMap(list -> readByName(list.getName()));
...在您的保存方法中,将获取您现有的列表并使用 readByName()
.
您的 readByName()
方法如下:
private Mono<List> readByName(final String listName) {
if (listName != "list001") {
return Mono.empty();
}
return createList(listName);
}
(我认为这与此问题无关,但 don't use == or != for comparing strings。)
由于您的 listName
是 foo
,而不是 list001
,它 return 是一个空的 Mono
- 因此 existingListMono
变成了一个空的单声道,并暗示 savedListMono
和 trueResult
.
然而,当您调用 switchIfEmpty()
语句时,您传入了 templateSave(existingListMono)
- 由于 existingListMono
如上所述是一个空的 Mono
,因此 save()
方法 returns 一个空 Mono
.
...当你阻塞一个空的 Mono
时你会得到 null - 因此结果。
因此,您可能希望在 save()
方法的 return 语句中使用 listMono
而不是 existingListMono
,这将为您提供结果再之后:
trueResult.switchIfEmpty(templateSave(listMono).map(x -> false))