有时我们需要在某个时间间隔在我们的组件中自动刷新/轮询。 这可以通过 Timer RxJS 操作符来实现。 但是让我们在没有 RxJS 的情况下这样做,看看我们犯了什么错误,然后我们会进化到最好的解决方案。
export class AutoRefreshTimerComponent implements OnInit,OnDestroy {
interval:any;
constructor(private dataService:DataService) {}
ngOnInit(): void {
this.getData();
this.interval = setInterval(()=>{
this.getData();
},10000);
}
getData(){
this.dataService.getDataFromAPI().pipe(
map((response:any)=>console.log(response))
).subscribe();
}
ngOnDestroy(): void {
clearInterval(this.interval);
}
}
我们在 ngOnInit 上调用 getData,因为我们需要在创建组件时第一次调用它。 然后我们使用在 window 对象上可用的 setInterval 方法。
this.interval = setInterval(()=>{
this.getData();
},10000);
此方法返回唯一标识区间的区间 ID。 我们将它存储到组件的间隔中,并在 ngOnDestroy 上清除间隔。
这种方法的问题是我们在每次通话时都订阅但没有取消订阅。
在处理 observables 时,RxJS 操作符是最好的。 因此,让我们利用区间运算符。
export class AutoRefreshTimerComponent implements OnInit, OnDestroy {
private unsub = new Subject<void>();
constructor(private dataService: DataService) {}
ngOnInit(): void {
this.getData().subscribe();
interval(10000)
.pipe(
tap((x) => console.log(x)),
takeUntil(this.unsub),
switchMap(() => this.getData())
)
.subscribe();
}
getData() {
return this.dataService
.getDataFromAPI()
.pipe(map((response: any) => console.log(response)));
}
ngOnDestroy(): void {
this.unsub.next();
this.unsub.complete();
}
}
interval 运算符以毫秒为单位并发出诸如 0,1,2,3 之类的值。在给定的间隔上,我们使用 switchMap 运算符将其映射到我们的 API 调用。 您可以在此处了解有关 switchMap 的所有信息。
上述方法的问题是,我们仍然是单独调用 getData 方法来第一次获取数据。
这可以使用 timer 运算符来解决。
export class AutoRefreshTimerComponent implements OnInit, OnDestroy {
private unsub = new Subject<void>();
constructor(private dataService: DataService) {}
ngOnInit(): void {
timer(0,15000).pipe(
tap((x)=>console.log(x)),
takeUntil(this.unsub),
switchMap(()=>this.getData())
).subscribe();
}
getData() {
return this.dataService
.getDataFromAPI()
.pipe(map((response: any) => console.log(response)));
}
ngOnDestroy(): void {
this.unsub.next();
this.unsub.complete();
}
}
timer 有两种口味。 timer(initialDelayInMilliSeconds) 采用一个参数,在给定的延迟时间后,它将发出一次值,然后完成。 timer(initialDelayInMilliSeconds,interval) 采用初始延迟和间隔时间。 它将在初始延迟后发出值,然后像区间运算符一样在给定的间隔上发出值。 所以通过这种方式,我们可以通过将 initialDelay 传递为 0 来解决初始调用问题。
我已使用 takeUntil 运算符取消订阅。
我希望这很清楚。