Angular2。如何检查观察结果是否已完成?

时间:2017-07-11 10:41:09

标签: angular rxjs angular2-observables

在我的页面中有一个生成报告的按钮。该报告需要在加载页面时使用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.
} 

一个选项是加载公司中设置的标志,其值为“loading”和“completed”,并在generateReport()中等待,直到标志完成为止, 但如果可能的话,我更倾向于使用Observable API的解决方案。

6 个答案:

答案 0 :(得分:10)

您可以在onCompleted中使用subscription回调来执行此操作。例如,假设您在用户按下报告按钮时显示加载栏;

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的文档。我希望它有所帮助!

答案 1 :(得分:3)

还有一个解决方案:

实际上,订阅功能有三个参数:

onNext onerror的 onCompleted

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

答案 2 :(得分:3)

在这种情况下,使用 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 :(得分:1)

方法

import numpy as np

array_3d = np.random.random_integers(50, 80, (3, 50, 18))
minimums = np.zeros(array_3d.shape)

for array_2d_index in range(len(array_3d)):
    for row_index in range(len(array_3d[array_2d_index])):
        for col_index in range(len(array_3d[array_2d_index][row_index])):
            minimums[array_2d_index][row_index][col_index] = min(array_3d[array_2d_index][np.clip(row_index-10, 0, 49):np.clip(row_index+10, 0, 49)][col_index])
  

在源可观察序列之后调用指定的操作   优雅地或特殊地终止。

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

答案 4 :(得分:0)

我想出的解决方案是使用共享的可观察对象,以这种方式将请求另存为热可观察对象,即在单击报告按钮时它将等待请求,或者如果请求完成则立即生成。

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

答案 5 :(得分:0)

如果要进行调试,最简单的解决方案是使用complete的{​​{1}}参数:

tap

使用来源tap(next: null, error: null, complete: () => void) 时,看起来像这样:

source$