angular - 如果 rxjs 仍在进行数据加载,如何返回数据或等待
问题描述
我有一个服务,它使用 Observable 在它的构造函数中加载一些数据。然后在稍后的某个时间,可以使用 getter 检索数据。如果数据存在,它应该立即返回数据。或者,如果仍在进行中,请等待加载完成。我想出了以下示例(代码在 Typescript 中):
class MyService {
private loadedEvent = new Subject<any>();
private loaded = false;
private data: any;
constructor(
private dataService: DataService
) {
this.dataService.loadData().subscribe(data => {
this.data = data;
this.loaded = true;
this.loadedEvent.next(null);
});
}
public getDataOrWait(): Observable<any> {
if (this.loaded) { // A
return of(this.data);
}
return new Observable((observer: Observer<any>) => {
const subscription = this.loadedEvent.subscribe(() => { // B
observer.next(this.data);
observer.complete();
subscription.unsubscribe();
});
});
}
}
有没有更简单的方法来做到这一点?这一定是一种常见的模式。
此外,我认为如果在标记为 A 和 B 的行之间的某处执行加载完成,则存在竞争条件(我不确定这里是否涉及线程 - 但是数据是异步加载的)。
解决方案
您所要做的就是使用shareReplay()运算符:
class MyService {
public data$: Observable<any>;
public loaded$: Observable<boolean>;
constructor(private dataService: DataService) {
this.data$ = this.dataService.loadData().pipe(
shareReplay(1);
);
this.loaded$ = this.data$.pipe(
mapTo(true),
startWith(false)
);
}
}
该shareReplay
运算符是一个多播运算符,它将向所有订阅者发出相同的先前值。订阅者将等到第一个值可用。
然后,您可以使用它data$
来创建一个loaded$
可观察的对象,该对象将一直发出false
直到data$
最终发出一个值,然后它总是会true
在值准备好时发出。
或者,您可以在数据准备好之前data$
发出null
数据,然后发出数据。下游有一些合乎逻辑的好处,允许您在数据准备好与否时创建新的 observables。
this.data$ = this.dataService.loadData().pipe(
startWith(null),
shareReplay(1);
);
您必须调用myService.data$.subscribe()
触发流的第一次读取以使数据准备好。您可以在构造函数中执行此操作,但请记住,Angular 在首次使用之前不会创建服务。如果您希望快速加载数据,请在路由中使用解析器或将服务注入NgModule
构造函数并在那里订阅。
推荐阅读
- sql-server - 使用 CASE 语句创建视图
- python - 创建项目后如何创建日期字段?
- razor-pages - razorpage 构造函数注入不起作用,而视图注入确实起作用
- react-native - 使用 AsyncStorage 的动态构建组件
- java - 如何在 SpannableString 的多个实例上显示不同的 toast 消息?
- javascript - 具有位置的旋转图像固定在 ReactJS 中动态更改旋转原点
- html - Vue.js 表单提交立即用 v-if 显示
- clickhouse - 未排序数组中的密集秩 (Clickhouse)
- javascript - 如何在javascript中修复“this.property is not iterable at window.onload”
- python-3.x - exec:名称未定义,但之前在同一代码中工作