javascript - Ionic 3 - Päivitä Observable asynkronisella datalla


Sosiaalisen median sovellusta varten minulla on kokoelma syötteen objekteja, joihin viitataan niiden tunnisteiden avulla käyttäen AngularFire 2-kirjastoa. Kun jokaisesta näistä tunnisteista on haettu siihen liittyvät tiedot tietokannasta, joka tallentaa varsinaiset syötteen objektit, haluan päivittää feedCards-Observable-objektin näillä tiedoilla, jotta voin asynkronisesti näyttää kokoelman syötteen objekteja HTML:ssäni. Tämä on melko hämmentävä tapahtumaketju, joten annan sinulle siitä yhteenvedon.

Askel askeleelta -lähestymistapa

  1. displayFeed() kutsutaan juuri ennen kuin NavController lataa feed-komponentin Main-sivulla.
  2. displayFeed() hakee twiner -kohteen, joka on pohjimmiltaan käyttäjäprofiilikohde, ja tallentaa sitten käyttäjäprofiilin userProfile-muuttujaan.
  3. Kun käyttäjäprofiili on ladattu, globaali feedCards Observable asetetaan yhtä suureksi kuin loadFeed(), joka palauttaa Observablen taulukon.
  4. loadFeed() käyttää userProfile-globaalin objektin id-arvoa ladatakseen käyttäjäprofiiliin tallennetut syöteviitteiden luettelot.
  5. Tätä tilannekuvaa tilataan sitten ja paikallinen feed-muuttuja asetetaan yhtä suureksi kuin syötereferenssien tuloslista.
  6. loadFeed palauttaa Observable-olion, jossa feed-viitelistä on kartoitettu sen datan mukaan, jota kukin feed-viite sisältää.
  7. pullFeedData(number) ottaa parametrikseen viitteen syötteen objektiin ja palauttaa observablen siihen liittyvillä syötedatan.

Mikä toimii

  • alert(JSON.stringify(feedData)); näyttää oikean feed-objektin ilmoituksena

  • Periaatteessa kaikki muu.

Mikä ei toimi

  • feed.map(... ei päivitä feed-taulukkoa, koska pullFeedData(number) hakee ja palauttaa feedData asynkronisesti. Siksi alert(JSON.stringify(data)); displayFeed()-funktiossa näyttää [null].

Koodi

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>

Yhteenveto

feed.map ei päivitä feed-objekteja, koska uutta dataa haetaan asynkronisesti. Tarvitsen tähän korjauksen.

Kiitos!

Vastaus #1

Tilattu observable ei palauta arvoa. Se palauttaa Subscription-objektin, jota voit käyttää peruuttaaksesi tilauksen myöhemmin.

Voit käyttää switchMap-metodia siirtyäksesi ensimmäisestä observable-objektista seuraavaan kutsun aikana ja palauttaa arvot. Voit myös käyttää forkJoin-metodia, joka kutsuu observables-taulukkoa ja odottaa, kunnes arvojen taulukko on palautettu tilauksessa. Määrittele ensin feed-luokan muuttuja Observable-tyyppisenä.

feed: Observable<any>;

Sitten sinun loadFeed():Observable<any[]>

return this.feed.switchMap((snapshots) => {
             let observableArray = [];
             snapshots.forEach(snapshot =>{
                 observableArray.push(this.pullFeedData(snapshot.val()));
             });
             return Observable.forkJoin(observableArray)
        })