javascript - Ionic 3 - Oppdater Observable med asynkrone data
For en sosial medieapp har jeg en samling av feed-objekter referert med deres ID-er ved bruk av AngularFire 2. Når hver av disse ID-ene har fått hentet relevant data fra databasen som lagrer de faktiske feed-objektene, ønsker jeg å oppdatere feedCards Observable-objektet med denne informasjonen slik at jeg kan vise en samling av feed-objekter asynkront i HTML-en min. Det er en ganske forvirrende kjede av hendelser, så la meg oppsummere det for deg.
Trinnvis tilnærming
displayFeed()blir kalt rett førNavControllerlasterfeed-komponenten påMain-siden.displayFeed()hentertwiner-elementet, som i hovedsak er et brukerprofil-element, og lagrer deretter brukerprofilen iuserProfile-variabelen.- Når brukerprofilen er lastet, settes den globale
feedCardsObservable likloadFeed(), som returnerer et Observable-array. loadFeed()brukerid-verdien tiluserProfile-globale objektet for å laste listen over feed-referanser lagret i brukerprofilen.- Dette øyeblikksbildet blir deretter abonnert på, og den lokale
feed-variabelen settes lik resultatlisten over feed-referanser. loadFeedreturnerer et Observable-objekt derfeed-referanselisten er kartlagt etter dataene hver feed-referanse inneholder.pullFeedData(number)tar inn en referanse til et feed-objekt og returnerer en observerbar med de tilknyttede feed-dataene.
Hva som fungerer
alert(JSON.stringify(feedData));viser den riktigefeed-objektetEgentlig alt annet.
Hva fungerer ikke
feed.map(...oppdaterer ikke feed-arrayet fordipullFeedData(number)henter og returnererfeedDataasynkront. Dermed vilalert(JSON.stringify(data));idisplayFeed()vise[null].
Kode
feed.ts userProfile:any;
feed: FirebaseListObservable<any>;
feedData: FirebaseObjectObservable<any>;
feedCards: Observable<any[]>;
constructor(public db: AngularFireDatabase, public nativeStorage: NativeStorage) {}
displayFeed():void {
this.nativeStorage.getItem('twiner').then((res) => {
this.userProfile = res;
this.feedCards = this.loadFeed();
this.feedCards.subscribe((data)=>{
alert(JSON.stringify(data));
})
});
}
loadFeed():Observable<any[]> {
var feed;
this.feed = this.db.list('/twiners/' + this.userProfile.id + '/feed', { preserveSnapshot: true });
this.feed.subscribe((snapshots)=>{feed = snapshots});
return Observable.of(feed.map((snapshot) => {
this.pullFeedData(snapshot.val()).subscribe((feedData)=>{
alert(JSON.stringify(feedData));
return feedData;
});
})).delay(1000);
}
pullFeedData(twine:number):any {
return this.db.object('/twines/' + twine, { preserveSnapshot: true });
}
feed.html<ion-content fullscreen scroll="true" overflow-scroll="true">
<ion-card *ngIf="feedCards | async">feedCards exist</ion-card>
<twine-feed-card *ngFor="let feedCard of feedCards | async"
[data]="feedCard"
></twine-feed-card>
</ion-content>
Sammendrag
feed.map oppdaterer ikke feed med feed-objekter fordi de nye dataene hentes asynkront. Jeg trenger en løsning på dette.
Takk!
Svar #1
Et abonnert observable returnerer ikke en verdi. Det returnerer et Subscription-objekt som du kan bruke til å avslutte abonnementet senere.
Du kan bruke switchMap for å bytte fra den første observable til den neste under kallingen og returnere verdiene. Du kan også bruke forkJoin som vil kalle et array av observables og vente til arrayet av verdier returneres i abonnementet. Først deklarer feed som en klassevariabel som en Observable.
feed: Observable<any>;
Deretter i din loadFeed():Observable<any[]>
return this.feed.switchMap((snapshots) => {
let observableArray = [];
snapshots.forEach(snapshot =>{
observableArray.push(this.pullFeedData(snapshot.val()));
});
return Observable.forkJoin(observableArray)
})
