Angular 2+ 有条件刷新实时数据而不刷新页面
Angular 2+ refreshing real time data conditionally without refreshing the page
我从API服务中得到一笔交易,条件是如果交易状态为'pending',继续重新加载并订阅交易,直到交易状态为'completed'或'rejected'。我的代码只在第一次运行,然后下次访问时,页面是空白的,但即使我取消订阅,数据仍在控制台中运行。
这是我的代码:
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();
}
}
}
我想不出没有副作用的解决方案,但我认为它可能对您有所帮助。 Rxjs 有一个 retry()
运算符,它会在它抛出时为你重新运行订阅。所以我会这样做:
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'
});
}
有了这个,理论上您可以删除所有其他订阅。
我从API服务中得到一笔交易,条件是如果交易状态为'pending',继续重新加载并订阅交易,直到交易状态为'completed'或'rejected'。我的代码只在第一次运行,然后下次访问时,页面是空白的,但即使我取消订阅,数据仍在控制台中运行。
这是我的代码:
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();
}
}
}
我想不出没有副作用的解决方案,但我认为它可能对您有所帮助。 Rxjs 有一个 retry()
运算符,它会在它抛出时为你重新运行订阅。所以我会这样做:
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'
});
}
有了这个,理论上您可以删除所有其他订阅。