web-dev-qa-db-ja.com

角度2。オブザーバブルが完了したかどうかを確認するにはどうすればよいですか?

私のページには、レポートを生成するボタンがあります。そのレポートには、ページのロード時にRESTエンドポイントへのhttp呼び出しを使用してロードされるデータが必要ですが、ユーザーがレポートボタンを押したときにロードされるという保証はありません。

監視可能オブジェクトを監視して、完了したかどうかを確認し、完了していない場合は、http呼び出しが完了するまでアクションを待機できますか?コードの一部を次に示します。

_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.
} 
_

1つのオプションは、値を「loading」および「completed」に設定して会社にロードするフラグです。フラグが完了するまでgenerateReport()で待機しますが、Observable可能であればAPI。

15
csm86

これを行うには、onCompletedsubscriptionコールバックを使用します。たとえば、ユーザーがレポートボタンを押したときに読み込みバーを表示するとします。

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

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

Http呼び出しからエラーが発生した場合、onCompletedメソッドは呼び出されず、onErrorのみが呼び出されます。成功すると、onCompletedメソッドの後にonNextメソッドが呼び出されます。

ここに subscribe のドキュメントがあります。お役に立てば幸いです!

12
ulubeyn

この種のシナリオでは、concatMap演算子を使用して、前の操作が完了した場合にのみ次の操作を実行することを保証すると非常に便利です。

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();
      }

    });
  }
3
yaircarreno

もう1つのソリューション:

実際にサブスクライブ関数は3つのパラメーターを取ります。

onNext onError onCompleted

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

方法

finally()

ソース監視可能シーケンスが正常にまたは例外的に終了した後、指定されたアクションを呼び出します。

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

1

私が思いついた解決策は、共有オブザーバブルを使用し、レポートボタンをクリックするとリクエストをホットオブザーバブルとして保存し、リクエストを待機するか、リクエストが完了するとすぐに生成することです。

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

更新:さらに一歩進んでUIを非同期にすることができます https://stackblitz.com/edit/check-if-an-observable-is-completed-async-ui?file=src%2Fapp% 2Fapp.component.html

0
William Lohan