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