简体   繁体   中英

Angular 6 Observable of custom object array loads once

I'm developing an application using Angular 6 angularfire2 firestore. At first everything looks good, I click (/list) the route to list my objects, the list is ok. But when I click /Home and then again click /list to list again, no list is shown, no errors in console. but if I refresh the page using F5 the list appears again.

Any ideas what am I doing wrong?

My service:



    import { AngularFirestoreCollection, AngularFirestoreDocument, AngularFirestore } from 'angularfire2/firestore';
    import { Personagem } from './../model/personagem';
    import { Observable } from 'rxjs/Observable';
    import { Injectable } from '@angular/core';

    @Injectable({
      providedIn: 'root'
    })
    export class PersonagemService {

      personagens: Observable;
      personagemColl: AngularFirestoreCollection;
      personagemDoc: AngularFirestoreDocument;

      constructor(private afs: AngularFirestore) { 
        this.personagemColl = this.afs.collection('personagem', ref=> ref.orderBy('nome', 'asc'));

        this.personagens = this.personagemColl.snapshotChanges().map(changes=> {
          return changes.map(p => {
            const data = p.payload.doc.data() as Personagem;
            data.id = p.payload.doc.id;
            return data;
          });
        });
      }

      getPersonagens() {
        return this.personagens;
      }

      addPersonagem(personagem: Personagem) {
        this.personagemColl.add(personagem);
      }

      deletePersonagem(personagem: Personagem) {
        this.getPersonagemDoc(personagem)
        this.personagemDoc.delete();
      }

      updatePersonagem(personagem: Personagem) {
        this.getPersonagemDoc(personagem)
        this.personagemDoc.update(personagem);
      }

      getPersonagemDoc(personagem: Personagem) {
        return this.personagemDoc = this.afs.doc(`personagem/${personagem.id}`); 
      }
    }

My Component:



    import { Router } from '@angular/router';
    import { PersonagemService } from './../../services/personagem.service';
    import { Component, OnInit } from '@angular/core';
    import { Observable } from '@firebase/util';
    import { Personagem } from '../../model/personagem';

    @Component({
      selector: 'app-listar-personagem',
      templateUrl: './listar-personagem.component.html',
      styleUrls: ['./listar-personagem.component.css']
    })
    export class ListarPersonagemComponent implements OnInit {

      personagens: Personagem[];

      constructor(private personagemServ: PersonagemService,
        private router: Router) {

      }

      ngOnInit() {
        this.personagemServ.getPersonagens().subscribe(personagens => {
          this.personagens = personagens;
          console.log('lenght', this.personagens.length);
        });
      }

    }

I FIXED IT

I changed the service like this:



      //personagens: Observable;
      personagemColl: AngularFirestoreCollection;
      personagemDoc: AngularFirestoreDocument;

      constructor(private afs: AngularFirestore) { 
        this.personagemColl = this.afs.collection('personagem', ref=> ref.orderBy('nome', 'asc'));
      }

      getPersonagens$(): Observable {
        return this.personagemColl.snapshotChanges().map(changes=> {
          return changes.map(p => {
            const data = p.payload.doc.data() as Personagem;
            data.id = p.payload.doc.id;
            return data;
          });
        });
      }

And the list component like this:



      personagens: Personagem[];

      constructor(private personagemServ: PersonagemService,
        private router: Router) {

      }

      ngOnInit() {
        this.personagemServ.getPersonagens$().subscribe(
          personagens => {
            this.personagens = personagens;
          });
      }

Thank you guys

Observables do not hold last values. Aka. when you subscribe to the personagens: Observable, you have to wait for something to push a new value there. So in your case, the first time you refresh, you subscribe to the observable before a value is pushed there. When the value is pushed, your list is initialized. When you move to /home and back to /list, you resubscribe to the observable, but since nothing new is pushed to that observable, your list remains uninitialized the second time.

You could look into BehaviourSubject, which is extended from Observable ( http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html )

在此处输入图片说明

Subject that emits the most recent item it has observed and all subsequent observed items to each subscribed Observer.

在此处输入图片说明

EDIT 1#

In addition, you do not terminate your subscriptions. If you do not terminate them, they are left open in the application, even when the component is destroyed, thus eventually creating a performance bottleneck.

this.personagemServ.getPersonagens().subscribe(personagens => {
          this.personagens = personagens;
          console.log('lenght', this.personagens.length);
        });

Here is a nice article about how to terminate subscriptions gracefully.

Angular/RxJs When should I unsubscribe from `Subscription`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM