RxJava订阅副作用

时间:2017-04-27 02:19:26

标签: rx-java reactive-programming side-effects

我有一个问题,这是简单的业务逻辑流程:

检查多个部门,部门和员工关系中的员工是否在缓存中,首先检查缓存中是否存在关系,如果存在,检查是否存在 员工属于它,如果不在缓存中,则从数据库中获取,并检查员工关系,然后将部门信息保存到缓存中。

这是代码:

public Observable  isEmployeeInDepartment(List<Long> departmentIds, long employeeId){

     //this observable will resolve twice, and cause unnecessary cache access
     Observable  departmentInfoExsitInCache= checkDepartmentInfoFromCache(...).share();   

     Observable  departInfoNotInCache = departmentInfoExsitInCache.filter(...);

     //this observable will resolve twice, and cause unnecessary database access
     Observable  departmentInfoFromDb=departInfoNotInCache.flatMap(departmentIds->checkFromDb()).share(); 

     Observable<Long> saveResult=departmentInfoFromDb.flatMap(departmentInfo->saveToCache());

     Observable<Long> departInfoInCache = departmentInfoExsitInCache.filter(...);

     return departInfoInCache.check(userId).merge( departmentInfoFromDb.check(userId)).doOnCompleted(saveResult.subscribe());
}

问题是,一旦客户端方法订阅,departmentInfoExsitInCache和saveResult将被解析两次。

我发现一旦删除了保存订阅代码.doOnCompleted(saveResult.subscribe()),它将变为正常并且只解析一次。这段代码有什么问题吗?

1 个答案:

答案 0 :(得分:0)

你在这里滥用分享。
问题是share()在这种情况下无法帮助您。 share()实际上publish().autoConnect()意味着保持对流的单一订阅,因此再次调用subscribe将不会再次调用订阅逻辑,而只是将您连接到现有流。 但是,在从共享流中取消订阅的所有订阅者之后,Observable将取消订阅,这意味着当您再次调用subscribe()时,您将调用订阅逻辑并再次调用DB / Cache。 / p>

因此,您正在做的是在取消订阅后再次订阅共享运营商。 (在doOnCompleted()中),这将导致departmentInfoFromDbdepartmentInfoExsitInCache再次订阅并转到DB / Cache。

考虑使用cache()/reply()运算符在订阅之间持久保存从DB / Cache获取的值。