昨天同事在某個頁面裡新增了一個「背景自動刷新頁面」的功能,而我在幫他 code review 之後趕緊請他改用 RxJS 實作這個功能,這是為什麼呢?
沒有要鞭同事的意思,純粹是藉機分享!
一般實作方式
一般用 JavaScript 實作的計時器大概會長這樣:
1 2 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 裡面實作為例):
1 2 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$
送出通知即可。
- 更好閱讀與更美觀
你覺得呢?