@Input() list: string[];
ngOnInit() : void {
this.valueMap = new Map<any, any>();
this.getDataFromService();
this.buildContainer();
}
private getDataFromService(): void {
this.list.forEach(value-> {
this.fetchService(value).subscribe(data ->{
this.valueMap.set(value,data);
}
)
})
}
private buildContainer(): void {
console.log(this.valueMap.size); // shows always 0 even when service returns the data
}
现在的问题是,我必须在方法valueMap
中使用这个buidlContainer()
,因此我需要首先从服务获得完整的映射。当我在buildConatainer()中使用该映射时,它会显示未定义的映射。
我知道这是一些异步调用问题。另外,我不能为.subscribe()中的每个值调用方法.subscribe(),因为这不是更好的主意。所以,在进一步处理之前,我必须先计算地图。
任何帮助都很感谢,我不能修改服务从返回可观察返回到返回承诺
我想做下面的工作
private buildContainer(): void {
for([key,data] of this.valueMap) {
-----some code----
}
}
发布于 2020-07-16 01:21:46
这是将反应性范例引入代码的缺点之一(或优势取决于您如何看待它)。一个单一的反应过程将逐渐渗透到代码的其他部分,部分或完全。
因此,我建议您也使valueMap
具有反应性,并根据getDataFromService()
服务中的更改做出响应。一种方法是使valueMap
变量成为一个缓冲区为1的RxJS ReplaySubject
,因此它将缓冲(或保存)它的最后一个值,并在订阅时立即发出它。
尝试以下几点
import { forkJoin, ReplaySubject, Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
valueMap: ReplaySubject<Map<any, any>> = ReplaySubject<Map<any, any>>(1);
completed$ = new Subject<any>();
@Input() list: string[];
ngOnInit(): void {
this.valueMap = new Map <any, any>();
this.getDataFromService();
this.buildContainer();
}
private getDataFromService(): void {
forkJoin(this.list.map(value => this.fetchService(value))).pipe(
takeUntil(this.completed$) // <-- close subscription upon component `ngOnDestroy` hook trigger
).subscribe(
data => {
let map = new Map<any, any>();
data.forEach((item, i) => {
map.set(this.list[i], item);
});
this.valueMap.next(map);
}
);
}
private buildContainer(): void {
this.valueMap.asObservable().pipe(
take(1) // <-- emit only the first notification and complete
).subscribe(
data => {
console.log(this.valueMap.size);
}
);
}
ngOnDestroy() {
this.completed$.next();
this.completed$.complete();
}
我还使用RxJS forkJoin()
函数组合了多个可观测值,当组件被破坏时,takeUntil
操作符关闭订阅。
工作示例:斯塔克布利茨
在这个示例中,我使用了HTTP来模拟jsonplaceholder
函数中的一些fetchService()
调用。
注意:
forkJoin()
才会发出。如果您正在处理数据流,则必须根据您的需求使用combineLatest
或zip
替换它。buildContainer()
函数,每个函数都将触发单个订阅。发布于 2020-07-15 23:38:20
只需使用forkJoin
等待所有可观察到的结果完成。forkJoin
将把所有可观测到的数据捆绑在一起。这个可观察到的可以返回,在ngOnInit
中您订阅它并调用buildContainer
。
@Input() list: string[];
ngOnInit(): void {
this.valueMap = new Map<any, any>();
this.getDataFromService().subscribe(_ => this.buildContainer());
}
private getDataFromService(): Observable<any> {
return forkJoin(
this.list.map(value =>
this.fetchService(value).pipe(
tap(data => this.valueMap.set(value, data))
)
)
);
}
private buildContainer(): void {
console.log(this.valueMap.size);
}
如果您不将valueMap
填充到tap
操作符中,而是使用您在订阅函数中得到的结果,代码就会更加简洁。
发布于 2020-07-15 23:17:47
从ngOnInit中删除ngOnInit并调用订阅中的方法
private getDataFromService(): void {
this.list.forEach((value, index) -> {
this.fetchService(value).subscribe(data ->{
this.valueMap.set(value,data);
}
)
if(this.list.length-1 == index){
this.buildContainer(); // call here
}
})
}
https://stackoverflow.com/questions/62929431
复制相似问题