棱角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.
} 

一种选择是在加载公司中设置一个值为"正在加载"和"已完成"的标志,并在generateReport()中等待,直到标志完成, 但如果可能的话,我更喜欢使用ObservableAPI 的解决方案。

您可以通过在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方法。

这是订阅文档。我希望它有所帮助!

还有一个解决方案:

实际上订阅函数需要三个参数:

下一页 onError on已完成

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.html

最新更新