I get a transaction from API service, the condition is if the transaction status is 'pending', keep reloading and subscribing the transaction until the transaction status is 'completed' or 'rejected'. My code only works for the first time, then next time visit, the page is blank but the data still runs in console even though I unsubscribed it.
Here is my code:
export class TransactionSummaryComponent implements OnInit, OnDestroy {
transaction: Models.Transaction = <Models.Transaction>{};
cancelling: boolean = false;
goToPayment: boolean = false;
private dataRefreshSub: Subscription;
private subscribeToDataSub: Subscription;
private timer: Observable<any>;
constructor(
private route: ActivatedRoute,
private router: Router,
private apiService: ApiService,
private zone: NgZone,
@Inject(PLATFORM_ID) private platformId: Object) { }
ngOnInit() {
if (isPlatformBrowser(this.platformId)) {
this.getTransaction();
}
}
getTransaction() {
this.route.paramMap
.switchMap((params: ParamMap) => this.apiService.getTransaction(params.get('id')))
.subscribe((transaction: Models.Transaction) => {
this.transaction = transaction;
if (this.transaction.status === 'Pending') {
this.refreshData();
}
});
}
refreshData() {
this.dataRefreshSub = this.route.paramMap
.switchMap((params: ParamMap) => this.apiService.getTransaction(params.get('id')))
.subscribe((transaction: Models.Transaction) => {
this.transaction = transaction;
this.subscribeToData();
});
}
subscribeToData() {
this.zone.runOutsideAngular(() => {
NgZone.assertNotInAngularZone();
this.timer = Observable.timer(1, 5000);
this.subscribeToDataSub = this.timer
.subscribe(() => {
this.refreshData();
});
});
}
ngOnDestroy() {
if (this.dataRefreshSub !== undefined) {
this.dataRefreshSub.unsubscribe();
}
if (this.subscribeToDataSub !== undefined) {
this.subscribeToDataSub.unsubscribe();
}
}
}
I couldn't come up with a solution that doesn't use side effects, but I think it may help you. Rxjs has a retry()
operator, which will rerun the subscription for you when it throws. So I'd do something like this:
getTransaction() {
this.route.paramMap
.switchMap((params: ParamMap) => this.apiService
.getTransaction(params.get('id'))
.do(transaction => this.transaction = transaction) // Bad side effect here, I'm not sure how can this be cleaned out.
.map(transaction => {
if(transaction.status === 'Pending') {
throw 'Pending';
}
return transaction;
})
// use .retry(N) to retry at most N times. This will infinitely retry
.retryWhen(errors => errors)
)
.subscribe((transaction: Models.Transaction) => {
// Here transaction will be 'Completed' or 'Rejected'
});
}
With this you can delete all other subscriptions, in theory.