現場回顧
每次啟動彈幕的時候會用setInterval產生一個定時器,每隔2秒產生一條新彈幕,一直迴圈。 當需要切換頁面需要關閉頁面時,使用clearInterval清理掉定時器,並且把已經產生的彈幕清空,簡略程式碼如下:
let barrageTimer = null;
// 迴圈生成彈幕,每次呼叫生成一條彈幕
function barrageStart() {
barrageTimer = setInterval(()=>{
createBarrage();
},2000);
}
// 關閉彈幕,並清理已生成的彈幕
function barrageEnd() {
clearInterval(barrageTimer);
barrageList = [];
}
// 小程式頁面每次載入時呼叫
onShow() {
barrageStart();
}
// 小程式頁面隱藏或切換後臺時呼叫
onHide() {
barrageEnd();
}
複製程式碼
當我寫完這段程式碼時,自信滿滿,覺得執行起來一定沒問題,結果呢...... 頁面裡的彈幕定時器還在歡快地跑著,絲毫沒有收到clearInterval的影響...... 可以說是很氣人了,但是還是要保持微笑...
問題總結
查詢MDN後,明確setInterval被執行後其實會返回一個定時器的id,每生成一個定時器都會返回其id,相當於每次進入頁面的時候,都產生了一個定時器,當頁面快速切換的時候,有可能clearInterval還沒有把本次頁面產生的定時器清除,barrageTimer又被新的定時器id給覆蓋了,造成總有定時器在跑的結果。 想要解決這個問題也很簡單,在產生新的定時器前,檢查下,只要有舊的定時器id,再停止一次,防止定時器id相互覆蓋即可。
function barrageStart() {
if (barrageTimer) {
clearInterval(barrageTimer);
}
barrageTimer = setInterval(()=>{
createBarrage();
},2000);
}
function barrageEnd() {
clearInterval(barrageTimer);
barrageTimer = 0;
barrageList = [];
}
複製程式碼
當然這還不夠,最好是能用一個陣列將定時器id直接存進去,需要清理的時候統一清理
let barrageTimer = null;
let barrageTimerList = []
function barrageStart() {
barrageTimer = setInterval(()=>{
createBarrage();
},2000);
barrageTimerList.push(barrageTimer)
}
function barrageEnd() {
barrageTimerList.forEach((item,index)=>{
clearInterval(item)
})
barrageTimerList = []
barrageTimer = 0;
barrageList = [];
}
複製程式碼