[英]Angular2. How can I check if an observable is completed?
In my page there is a button that generates a report.在我的页面中有一个生成报告的按钮。 That report needs data that is loaded using a http call to a rest endpoint when the page is loaded, but I do not have a guarantee that they are loaded when the user presses the report button.
该报告需要在页面加载时使用对 rest 端点的 http 调用加载的数据,但我不能保证当用户按下报告按钮时它们会被加载。
How can I watch the observable to see if it is completed, and if incomplete, to wait on the action until the http call is completed?我如何观察可观察对象是否已完成,如果未完成,则等待操作直到 http 调用完成? Here is some of the code:
这是一些代码:
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.
}
One option is a flag set in loading companies with values of 'loading' and 'completed', and make a wait in generateReport()
until the flag is completed, but I would prefer a solution using the Observable
API if possible.一种选择是在加载公司中设置标志,其值为“正在加载”和“已完成”,并在
generateReport()
中等待直到标志完成,但如果可能,我更喜欢使用Observable
API 的解决方案。
You can do this by using onCompleted
callback in subscription
.您可以通过在
subscription
中使用onCompleted
回调来做到这一点。 For example, let's say you show loading bar when user press report button;例如,假设您在用户按下报告按钮时显示加载栏;
loadCompanies(): void {
this._companyService.getCompanies().subscribe(
response => {
this.companiesModel = response;
},
err => {
console.log(err);
//closeLoadingBar();
},
() => {
//do whatever you want
//closeLoadingBar()
}
)
}
generateReport() {
//showLoadingBar()
this.loadCompanies();
}
If you get error from your http call, onCompleted
method will not be invoked, only onError
will be invoked.如果您从 http 调用中收到错误,则不会调用
onCompleted
方法,只会调用onError
。 If it is successful, onCompleted
method will be called after your onNext
method.如果成功,将在您的
onNext
方法之后调用onCompleted
方法。
Here is the documentation for subscribe .这是subscribe的文档。 I hope it helps!
我希望它有所帮助!
One more solution:另一种解决方案:
Actually subscribe function takes three parameters:实际上 subscribe 函数需要三个参数:
onNext onError onCompleted onNext onError onCompleted
this._companyService.getCompanies().subscribe(
(response) => { this.companiesModel = response; },
(err) => { console.log(err) },
(finally) => { console.log('finally') }
);
Method方法
finally()
Invokes a specified action after the source observable sequence terminates gracefully or exceptionally.
在源可观察序列正常或异常终止后调用指定的操作。
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/finally.md https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/finally.md
In this kind of scenarios it is very useful to use concatMap operator to guarantee to execute the next operation only when the previous has done.在这种情况下,使用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();
}
});
}
If you're doing this to debug, the simplest solution is to use the complete
argument of tap
:如果您这样做是为了调试,最简单的解决方案是使用
tap
的complete
参数:
tap(next: null, error: null, complete: () => void)
With a source source$
it would look like this:使用源
source$
它看起来像这样:
source$.pipe(
tap(undefined, undefined, console.log)
);
The solution I came up with is to use a shared observable, save the request as a hot observable that way when the report button is clicked it will wait for the request or immediately generate if the request is complete.我想出的解决方案是使用共享的可观察对象,将请求保存为热可观察对象,这样当单击报告按钮时它将等待请求或在请求完成时立即生成。
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 https://stackblitz.com/edit/check-if-an-observable-is-completed?file=src%2Fapp%2Fapp.component.ts
Update: You could take it one step further and make the UI async https://stackblitz.com/edit/check-if-an-observable-is-completed-async-ui?file=src%2Fapp%2Fapp.component.html更新:您可以更进一步,使 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.