## 範例
範例程式如下:
```js
const express = require("express");
const app = express();
const users = new Map();
function newConnect() {
const user = new User("user_1");
users.set("user_1", user);
}
function disconnect() {
users.delete("user_1");
}
class User {
constructor(username) {
this.username = username;
this.bigData1 = "bigDataHello".repeat(1000000);
this.bigData2 = "bigDataHello,".repeat(1000000).split(",");
this._startTimer();
}
_startTimer() {
this.timer = setInterval(() => {
console.log(this.username);
}, 1000);
}
}
app.listen(3120, (err) => {
if (err) {
console.log(err);
} else {
console.log("建立 Server: " + `http://localhost:3120`);
}
});
app.get("/userEnter", (req, res) => {
newConnect();
res.send("用戶連線");
});
app.get("/userLeave", (req, res) => {
disconnect();
res.send("用戶離線");
});
```
在用戶連線進來之後,會產生一個 User 實例,並且啟動 interval 開始每秒 log username。
用戶離線之後刪除 User 實例在 users 的引用,照理說應該 User 就應該要被 GC 清理掉。
但是經過檢測發現 User 仍然存在 memory 中,並且那些巨大的 data 也依然存在。
- 用戶連線後,產生 User 實例與 bigData

- 用戶離線後,User 實例與 bigData 還在

原因是由於 setInterval 會不斷試圖存取該 User 中的 username,導致 User 實例無法被清除,連同 User 中的其他屬性也一併無法清除掉,即使他們並沒有被使用。
可參考:
[Forgotten Timers](https://betterstack.com/community/guides/scaling-nodejs/high-performance-nodejs/nodejs-memory-leaks/#causes-of-memory-leaks)
[Closures](https://betterstack.com/community/guides/scaling-nodejs/high-performance-nodejs/nodejs-memory-leaks/#2-closures)
修改後的程式:
```js
// ...以上省略
function disconnect() {
const user = users.get("user_1");
/* 離線後要記得清除 Timer */
user.clearTimer();
users.delete("user_1");
}
class User {
constructor(username) {
this.username = username;
this.bigData1 = "bigDataHello".repeat(1000000);
this.bigData2 = "bigDataHello,".repeat(1000000).split(",");
this._startTimer();
}
_startTimer() {
this.timer = setInterval(() => {
console.log(this.username);
}, 1000);
}
clearTimer() {
clearInterval(this.timer);
}
}
```
修改後再測試一次:
- 用戶連線後,產生 User 實例與 bigData

- 用戶離線後,User 被確實清除掉

## 實際案例
在 TV 中台程式裡面,有一個處理用戶報價連線的 class,其中使用了一個 Timer 來打 HeartBeat,但是用戶離線後並沒有清除這個 Timer,導致大量的相關依賴物件無法被GC清除
- HeartBeat Timer

### 檢測:
- 連線前:

- 5 用戶連線中:

- 5 用戶離線:

---
一樣在離線後加上 clearInterval,就能正常清出使用過的物件:

### 檢測:
- 連線前:

- 5 用戶連線中:

- 5 用戶離線:
