0

我最近一直在使用 Java 中的反应器库和 Spring 框架来学习反应式编程,并且在大多数情况下我已经能够掌握它。但是,我发现自己有几次处于同样的境地,并希望得到一些关于我哪里出错的建议。

我苦苦挣扎的要点通常是我想用单声道做一些事情,比如找到一些补充数据,然后将其添加回原始单声道。zip 功能在我看来是理想的候选人,但我最终订阅了原始单声道两次,这不是我的意图。

这是我一直试图解决的情况类型的人为示例,因为我无法共享我的公司代码。它假设我们使用的是响应式数据库并设置了记录器,并且 Person 类是不可变的,但具有 with<FieldName> 方法。

public Mono<Person> getPersonWithFamilyMembers(Integer id){
    log.info("Finding person with id {}", id);

    personRepository.findById(id)
        .switchIfEmpty(Mono.error(NotFoundException::new))
        .doOnNext(person -> log.info("Found person: {}", person))
        .as(this::fetchAndAddFamilyMembers)
        .doOnSuccess(person -> log.info("Successfully found person with family members"));
}

private Mono<Person> fetchAndAddFamilyMembers(Mono<Person> personMono){
    Mono<List<Person>> familyMembersMono = personMono
        .map(Person::getFamilyId)
        .flatMapMany(PersonRepository::findByFamilyId)
        .collectList();

    return personMono.zipWith(familyMembersMono, Person::withFamilyMembers);
}

我在运行这样的代码时看到的输出是:

INFO | Finding person with id 1
INFO | Found person: Person(id=1, familyId=1, familyMembers=[])
INFO | Found person: Person(id=1, familyId=1, familyMembers=[])
INFO | Successfully found person with family members

这确实是有道理的,因为原始人 mono 已在两个地方订阅,我将其映射到familyMembersMono和将它们压缩在一起时,但如果可以避免的话,我不想对存储库进行不必要的调用。

有人对处理这种行为的更好方法提出建议吗?

4

1 回答 1

1

通常,您不会向 Mono“添加数据”,而是向其中的数据添加数据。考虑到这一点,使用flatMap代替as

public Mono<Person> getPersonWithFamilyMembers(Integer id){
    log.info("Finding person with id {}", id);

    return personRepository.findById(id)
        .switchIfEmpty(Mono.error(NotFoundException::new))
        .doOnNext(person -> log.info("Found person: {}", person))
        .flatMap(this::fetchAndAddFamilyMembers)
        .doOnSuccess(person -> log.info("Successfully found person with family members"));
}

private Mono<Person> fetchAndAddFamilyMembers(Person person){ // this accepts Person, not Mono<Person>
    return personRepository.findByFamilyId(person.getFamilyId())
        .collectList()
        .map(person::withFamilyMembers);
}
于 2020-02-12T15:16:53.470 回答