使用setInterval與clearInterval踩的小坑總結

現場回顧

每次啓動彈幕的時候會用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相互覆蓋便可。bash

function barrageStart() {
  if (barrageTimer) {
    clearInterval(barrageTimer);
  }
  barrageTimer = setInterval(()=>{
    createBarrage();
  },2000);
} 

function barrageEnd() {
  clearInterval(barrageTimer);
  barrageTimer = 0;
  barrageList = [];  
}
複製代碼

固然這還不夠,最好是能用一個數組將定時器id直接存進去,須要清理的時候統一清理ide

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 = [];  
}
複製代碼
相關文章
相關標籤/搜索