用 RxJS 翻轉你的 coding 人生 - 以 Timer 為例

自製梗圖

昨天同事在某個頁面裡新增了一個「背景自動刷新頁面」的功能,而我在幫他 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) {
// do something..
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 來實作到底好在哪裡呢?

我個人覺得有以下三個好處:

  1. 計時器要做的事情在初始化的時候就做好了,後續不用再重做第二次
  2. 由於有上一點的好處,所以實際在執行動作的時候,就只要用 start$stop$ 送出通知即可。
  3. 更好閱讀與更美觀

你覺得呢?

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×