Angular:组合多个订阅



我尝试执行几个请求并将各自的结果结合在一起。

我有一个服装列表,它反过来可以包含服装项目的id。当我调用页面时,我尝试使用ID从服务器获取衣服。从这个服务中,我得到了每一件衣服的可观察对象。

我如何从这些可观察对象中读取数据并在最后合并它们?

然后通过*ngfor循环输出合并后的数据。如果我像下面的代码那样尝试,订阅函数需要更长的时间,直到数据已经存在,并且到那时已经执行了所有其他操作。所以在HTML文件中数据是未定义的。对不起,我希望我能澄清我的问题。

PageComponent.ts:

ngOnInit() {
this.isLoading = true;
this.outfitSub = this.outfitService.outfits.subscribe(outfits => {
this.geladeneOutfits = outfits;
});
}
ionViewWillEnter() {
this.isLoading = true;
this.outfitService.fetchOutfit().subscribe(() => {
this.geladeneOutfits.map(outfit => {
this.kleiderschrankService.getKleidungsstueck(outfit.oberteil1).subscribe(teil => {
this.oberteil1 = teil;
});
if(outfit.oberteil2 != null){
this.kleiderschrankService.getKleidungsstueck(outfit.oberteil2).subscribe(teil => {
this.oberteil2 = teil;
});
}
if(outfit.oberteil3 != null){
this.kleiderschrankService.getKleidungsstueck(outfit.oberteil3).subscribe(teil => {
this.oberteil3 = teil;
});
}
var outfitf = new OutfitKl (
this.oberteil1,
this.oberteil2,
this.oberteil3,
this.unterteil1,
this.unterteil2,
this.schuhe,
this.accessoir1,
this.accessoir2,
outfit.imageUrl
)
this.gezeigteOutfits.push(outfitf);
});
this.isLoading = false
});
}

PageComponent.html:

<ion-grid *ngIf="!isLoading && gezeigteOutfits.length > 0">
<ion-row no-padding>
<ion-col>
<div>
<ion-card *ngFor="let outfit of gezeigteOutfits">
<img [src]="outfit.imageUrl" >
<ion-card-header>
<ion-card-subtitle>Kleidungsstuecke</ion-card-subtitle>
<ion-card-title>Oberteile</ion-card-title>
</ion-card-header>
<ion-card-content>
<ion-grid>
<ion-row no-padding>
<ion-col size="4" size-sm="3" offset-sm="2">
<div>
<ion-img [src]="outfit.oberteil1.imageUrl">
</ion-img>
<ion-img [src]="outfit.schuhe.imageUrl"></ion-img>
</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-card-content>
</ion-card>
</div>
</ion-col>
</ion-row>
</ion-grid>

KleiderschrankService:

getKleidungsstueck(kleidungsstueckId: string) {
const kleidungsstueckDocs = this.store
.collection("Kleidungsstueck")
.doc(kleidungsstueckId);
return kleidungsstueckDocs.snapshotChanges().pipe(
map((changes) => {
const data = changes.payload.data();
return data;
})
);
}

来自RxJS的combinellatest应该可以做到这一点。

你可以这样写:

const first$ = this.kleiderschrankService.getKleidungsstueck(outfit.oberteil1);
const second$ = this.kleiderschrankService.getKleidungsstueck(outfit.oberteil2);
const third$ = this.kleiderschrankService.getKleidungsstueck(outfit.oberteil3);
combineLatest(first$, second$, third$).subscribe(([v1, v2, v3]) => {
//call the this.gezeigteOutfits.push(...) part here so it executes after the data has been recieved
});

我试图提供确切的解决方案,但由于缺乏信息,这是最:

ngOnInit() {
this.outfitSub = combineLatest(this.outfitService.outfits, this.outfitService.fetchOutfit()).subscribe(
([geladeneOutfits]) => {
geladeneOutfits.forEach(outfit => {
const subOb = [this.kleiderschrankService.getKleidungsstueck(outfit.oberteil1)];
outfit.oberteil2 && subOb.push(this.kleiderschrankService.getKleidungsstueck(outfit.oberteil2));
outfit.oberteil3 && subOb.push(this.kleiderschrankService.getKleidungsstueck(outfit.oberteil3));
(combineLatest.apply(this, subOb) as Observable<[any, any, any]>)
.subscribe(([ret1, ret2, ret3]) => {})
})
}
);
}

使用RxJS中的combinellatest并使用filter(),点击()来检查数据

combineLatest(
observable1,
observable2,
observable3
).pipe(
filter(data => !!data), 
tap(data => console.log(data)) 
catchError(error => console.log(error))
).subscribe(
[dataFromObs1, dataFromObs2, dataFromObs33] => {
// This will subscribe only if all the observables return data
// Otherwise it will go to catchError
})

// Filter will check if the data is present or not.
// Tap will return the data before subscribing
// catchError ==> Subscription errors are caught in this catchError

最新更新