【问题标题】:Combine two Mono's together where the second mono is subscribed to the first one将两个 Mono 组合在一起,其中第二个 Mono 订阅了第一个
【发布时间】:2020-02-11 15:11:03
【问题描述】:

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

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

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

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 并且当我将它们压缩在一起时,但我不想对存储库进行不必要的调用,如果我可以避免它。

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

【问题讨论】:

    标签: java project-reactor spring-reactive zipwith spring-reactor


    【解决方案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);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-24
      • 2019-05-25
      • 1970-01-01
      • 2021-07-31
      • 2022-11-16
      • 2019-09-09
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      相关资源
      最近更新 更多