
昨天同事在某個頁面裡新增了一個「背景自動刷新頁面」的功能,而我在幫他 code review 之後趕緊請他改用 RxJS 實作這個功能,這是為什麼呢?
沒有要鞭同事的意思,純粹是藉機分享!
一般實作方式
一般用 JavaScript 實作的計時器大概會長這樣:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | var REFRESH_PERIOD_SECOND = 30;
 var timer;
 var counter = 0;
 
 function startTimer() {
 timer = setInterval(function () {
 counter += 1;
 if (counter >= REFRESH_PERIOD_SECOND) {
 
 resetTimer();
 }
 }, 1000);
 }
 
 function resetTimer() {
 stopTimer();
 startTimer();
 }
 
 function stopTimer() {
 clearInterval(timer);
 counter = 0;
 }
 
 startTimer();
 
 | 
完整程式碼範例: JS Bin
用 RxJS 的實作方式
換用 RxJS 來實作的話大概會長這樣(以在 Angular 裡面實作為例):
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | @Component({
 })
 export class AppComponent implements OnInit {
 count = 0;
 
 private readonly REFRESH_PERIOD_SECOND = 30;
 
 private start$ = new Subject();
 private stop$ = new Subject();
 
 private timer$ = this.start$.pipe(
 switchMap(() => interval(1000).pipe(map((count) => count + 1))),
 tap((count) => (this.count = count)),
 filter((count) => count === this.REFRESH_PERIOD_SECOND),
 takeUntil(this.stop$),
 repeat()
 );
 
 ngOnInit(): void {
 this.timer$.subscribe(() => this.resetTimer());
 this.startTimer();
 }
 
 startTimer(): void {
 this.start$.next(null);
 }
 
 stopTimer(): void {
 this.count = 0;
 this.stop$.next(null);
 }
 
 resetTimer(): void {
 this.stopTimer();
 this.startTimer();
 }
 }
 
 | 
完整程式碼範例: Stackblitz
所以說,改用 RxJS 來實作到底好在哪裡呢?
我個人覺得有以下三個好處:
- 計時器要做的事情在初始化的時候就做好了,後續不用再重做第二次
- 由於有上一點的好處,所以實際在執行動作的時候,就只要用 start$或stop$送出通知即可。
- 更好閱讀與更美觀
你覺得呢?