我很难找到新的解决方案来兑现对BehaviorSubject的http请求。我只想有一种兑现和获取价值的方法。下面的示例:
@Injectable({
providedIn: 'root'
})
export class DataStoreService {
private readonly initialState: DataState = {
data: string,
loaded: false
};
private data$: BehaviorSubject<DataState> = new BehaviorSubject<DataState>(this.initialState);
constructor(private dataService: DataService) { }
getData$(id: string): Observable<string> {
return this.data$.asObservable()
.pipe(
switchMap((state: DataState) => {
if (!state.loaded) {
this.dataService.getData$(id);
} else {
return of(state.data);
}
}),
withLatestFrom(this.data$.asObservable()),
map(([data, state]) => {
if (!state.loaded) {
this.data$.next({
loaded: true,
data
});
}
return data;
})
);
}
}
我尚未测试(服务无法正常工作),但目前看来还可以。有人知道有什么更好的解决方案,可以在rxjs中使用较少的管道和条件(如果/其他)吗?
答案 0 :(得分:1)
BehaviourSubject在“ .value”中确实有一个非常简单的值访问器。
因此您的代码可能类似于
getData$(id: String): Observable<string> {
const dataValue = this.data$.value;
if (dataValue.loaded === true) {
return of(dataValue.data);
} else {
return this.dataService.getData$(id).pipe( map( (result: string) => { this.data$.next({ loaded: true, data: result}; return of(result); );
}
}
希望这会有所帮助。
答案 1 :(得分:1)
我的看法有所不同,实际上并没有使用行为主题,只是一个变量。如果您愿意这样做,则可以考虑:
data;
getData$(id: string): Observable<string> {
if (data) {
return of(data)
} else {
return this.dataService.getData$(id).pipe(
tap(dat => this.data = dat)
)
}
}
答案 2 :(得分:1)
您可以使用运算符BehaviorSubject
代替shareReplay
,该运算符在内部使用ReplaySubject
并向将来的订户重放n个最新值。
private data$: Observable<string>;
getData$(id: string): Observable<string> {
if (!this.data$) {
this.data$ = this.dataService.getData$(id).pipe(shareReplay(1));
}
return this.data$;
}
对getData$
的第一个订阅将称为this.dataService.getData$
。所有以后的订阅都将从data$
重播的第一个呼叫中获取数据。