簡體   English   中英

角度2。 如何檢查可觀察對象是否已完成?

[英]Angular2. How can I check if an observable is completed?

在我的頁面中有一個生成報告的按鈕。 該報告需要在頁面加載時使用對 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.
} 

一種選擇是在加載公司中設置標志,其值為“正在加載”和“已完成”,並在generateReport()中等待直到標志完成,但如果可能,我更喜歡使用Observable API 的解決方案。

您可以通過在subscription中使用onCompleted回調來做到這一點。 例如,假設您在用戶按下報告按鈕時顯示加載欄;

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 如果成功,將在您的onNext方法之后調用onCompleted方法。

這是subscribe的文檔。 我希望它有所幫助!

另一種解決方案:

實際上 subscribe 函數需要三個參數:

onNext onError onCompleted

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

方法

finally()

在源可觀察序列正常或異常終止后調用指定的操作。

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

在這種情況下,使用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();
      }

    });
  }

如果您這樣做是為了調試,最簡單的解決方案是使用tapcomplete參數:

tap(next: null, error: null, complete: () => void)

使用源source$它看起來像這樣:

source$.pipe(
  tap(undefined, undefined, console.log)
);

我想出的解決方案是使用共享的可觀察對象,將請求保存為熱可觀察對象,這樣當單擊報告按鈕時它將等待請求或在請求完成時立即生成。

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。網頁格式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM