来自 http 调用的 RxJS BehaviorSubject 兑现请求
RxJS BehaviorSubject cashing request from http call
我很难找到将 http 请求兑现到 BehaviorSubject 的 neet 解决方案。我希望只有一种方法来兑现和获得价值。示例如下:
@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 中使用更少的管道和条件 (if/else) 的更好的解决方案吗?
BehaviourSubjects 在“.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); );
}
}
希望对您有所帮助。
我对此的看法有点不同,实际上并没有使用行为主题,只是一个变量。如果这是您的选择,您可以考虑:
data;
getData$(id: string): Observable<string> {
if (data) {
return of(data)
} else {
return this.dataService.getData$(id).pipe(
tap(dat => this.data = dat)
)
}
}
您可以使用运算符 shareReplay
而不是 BehaviorSubject
,它在内部使用 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$
.
重播的第一个调用中获取数据
我很难找到将 http 请求兑现到 BehaviorSubject 的 neet 解决方案。我希望只有一种方法来兑现和获得价值。示例如下:
@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 中使用更少的管道和条件 (if/else) 的更好的解决方案吗?
BehaviourSubjects 在“.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); );
}
}
希望对您有所帮助。
我对此的看法有点不同,实际上并没有使用行为主题,只是一个变量。如果这是您的选择,您可以考虑:
data;
getData$(id: string): Observable<string> {
if (data) {
return of(data)
} else {
return this.dataService.getData$(id).pipe(
tap(dat => this.data = dat)
)
}
}
您可以使用运算符 shareReplay
而不是 BehaviorSubject
,它在内部使用 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$
.