web-dev-qa-db-fra.com

Angulaire2. Comment puis-je vérifier si un observable est terminé?

Dans ma page il y a un bouton qui génère un rapport. Ce rapport a besoin de données chargées à l’aide d’un appel http vers un noeud final de repos lors du chargement de la page, mais je n’ai aucune garantie qu’elles soient chargées lorsque l’utilisateur appuie sur le bouton du rapport.

Comment puis-je regarder l'observable pour voir s'il est terminé et, s'il est incomplet, attendre l'action jusqu'à ce que l'appel http soit terminé? Voici une partie du code:

loadCompanies(): void {
    this._companyService.getCompanies().subscribe(
        response => {
            this.companiesModel = response;
        },
        err => console.log(err)
    );
}
generateReport() {
   // check if observable that loads companies is completed and do the 
   // action using companiesModel.
} 

Une option consiste à définir un indicateur dans les entreprises de chargement avec les valeurs 'chargement' et 'terminé', et attendre generateReport() jusqu'à ce qu'il soit terminé, Mais je préférerais une solution utilisant si possible l'API Observable.

12
csm86

Vous pouvez le faire en utilisant onCompleted callback dans subscription. Par exemple, disons que vous affichez la barre de chargement lorsque l'utilisateur appuie sur le bouton de rapport;

loadCompanies(): void {
     this._companyService.getCompanies().subscribe(
          response => {
               this.companiesModel = response;
          },
          err => {
               console.log(err);
               //closeLoadingBar();
          },
          () => {
               //do whatever you want
               //closeLoadingBar()
          }
     )
}

generateReport() {
    //showLoadingBar()
    this.loadCompanies();
}

Si vous obtenez une erreur de votre appel http, la méthode onCompleted ne sera pas appelée, seule onError sera invoquée. Si elle réussit, la méthode onCompleted sera appelée après votre méthode onNext.

Voici la documentation pour subscribe . J'espère que ça aide!

10
ulubeyn

Une autre solution:

En fait, la fonction subscribe prend trois paramètres: 

onNext onError onCompleted

this._companyService.getCompanies().subscribe(
    (response) => { this.companiesModel = response; },
    (err) => { console.log(err) },
    (finally) => { console.log('finally') }
);
3
Valery Lyatsevich

Dans ce type de scénario, il est très utile d’utiliser concatMap operator pour s’assurer d’exécuter la prochaine opération uniquement lorsque la précédente l’a fait. 

loadCompanies(): void {
    this._companyService.getCompanies()
    .concatMap(companyList => this.getObservableGenerateReport(companyList))
    .subscribe(
        response => {
            this.companiesModel = response;
        },
        err => console.log(err)
    );
}


//Create observable to generate the report
getObservableGenerateReport(response: any): Observable<myReportList> {

    return Observable.create(observer => {

      if (generateReport().isSuccessful) {
        observer.next(myReportList);
        observer.complete();
      } else {
        console.log(err, 'Ups, something was wrong!');
        observer.next({});
        observer.complete();
      }

    });
  }
2
yaircarreno

Méthode 

finally()

Invoque une action spécifiée après la séquence observable source se termine gracieusement ou exceptionnellement.

https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/finally.md

1
Valery Lyatsevich

La solution que j’ai suggérée est d’utiliser un observable partagé, d’enregistrer la requête en tant qu’observable à chaud. Ainsi, lorsque vous cliquerez sur le bouton de rapport, il attendra la requête ou le générera immédiatement si la requête est complète.

public companiesModel: Company[];

/** pending request, hot Observable (will emit immediately if complete) */
private companiesRequest: Observable<Company[]>;

constructor(
  private _companyService: CompanyService
) {}

public ngOnInit(): void {
  this.loadCompanies();
}

public generateReport(): void {
  if (this.companiesRequest) {
    // will not make an other network request
    this.companiesRequest.subscribe(
      response => {
        // action using companiesModel.
      },
      err => console.log(err)
    );
  }
}

private loadCompanies(): void {
  this.companiesRequest = this._companyService.getCompanies().pipe(shareReplay());
  this.companiesRequest.subscribe(
    response => {
      this.companiesModel = response;
    },
    err => console.log(err)
  );
}

https://stackblitz.com/edit/check-if-an-observable-is-completed?file=src%2Fapp%2Fapp.component.ts

Mise à jour: vous pouvez aller un peu plus loin et rendre l’UI async https://stackblitz.com/edit/check-if-an-observable-is-completed-async-ui?file=src%2Fapp % 2Fapp.component.html

0
William Lohan