溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript定時器在頁面最小化時不執(zhí)行怎么實現(xiàn)

發(fā)布時間:2022-07-13 10:42:25 來源:億速云 閱讀:581 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“javascript定時器在頁面最小化時不執(zhí)行怎么實現(xiàn)”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“javascript定時器在頁面最小化時不執(zhí)行怎么實現(xiàn)”吧!

    useInterval 和 useTimeout

    看名稱,我們就能大概知道,它們的功能對應的是 setInterval 和 setTimeout,那對比后者有什么優(yōu)勢?

    先看 useInterval,代碼簡單,如下所示:

    function useInterval(
      fn: () => void,
      delay: number | undefined,
      options?: {
        immediate?: boolean;
      },
    ) {
      const immediate = options?.immediate;
      const fnRef = useLatest(fn);
      useEffect(() => {
        // 忽略部分代碼...
        // 立即執(zhí)行
        if (immediate) {
          fnRef.current();
        }
        const timer = setInterval(() => {
          fnRef.current();
        }, delay);
        // 清除定時器
        return () => {
          clearInterval(timer);
        };
        // 動態(tài)修改 delay 以實現(xiàn)定時器間隔變化與暫停。
      }, [delay]);
    }

    跟 setInterval 的區(qū)別如下:

    • 可以支持第三個參數(shù),通過 immediate 能夠立即執(zhí)行我們的定時器。

    • 在變更 delay 的時候,會自動清除舊的定時器,并同時啟動新的定時器。

    • 通過 useEffect 的返回清除機制,開發(fā)者不需要關(guān)注清除定時器的邏輯,避免內(nèi)存泄露問題。這點是很多開發(fā)者會忽略的點。

    useTimeout 跟上面很類似,如下所示,不再做額外解釋:

    function useTimeout(fn: () => void, delay: number | undefined): void {
      const fnRef = useLatest(fn);
      useEffect(() => {
        // ...忽略部分代碼
        const timer = setTimeout(() => {
          fnRef.current();
        }, delay);
        return () => {
          clearTimeout(timer);
        };
      // 動態(tài)修改 delay 以實現(xiàn)定時器間隔變化與暫停。
      }, [delay]);
    }

    setTimeout 和 setInterval 的問題

    首先,setTimeout 和 setInterval 作為事件循環(huán)中宏任務的“兩大主力”,它的執(zhí)行時機不能跟我們預期一樣準確的,它需要等待前面任務的執(zhí)行。比如下面的 setTimeout 的第二個參數(shù)設(shè)置為 0,并不會立即執(zhí)行。

    setTimeout(() => {
      console.log('test');
    }, 0)

    另外還有一種情況,setTimeout 和 setInterval 在瀏覽器不可見的時候(比如最小化的時候),不同的瀏覽器中設(shè)置不同的時間間隔的時候,其表現(xiàn)不一樣。根據(jù) 當瀏覽器切換到其他標簽頁或者最小化時,你的js定時器還準時嗎? 結(jié)論如下:

    谷歌瀏覽器中,當頁面處于不可見狀態(tài)時,setInterval 的最小間隔時間會被限制為 1s?;鸷鼮g覽器的 setInterval 和谷歌特性一致,但是 ie 瀏覽器沒有對不可見狀態(tài)時的 setInterval 進行性能優(yōu)化,不可見前后間隔時間不變。

    在谷歌瀏覽器中,setTimeout在瀏覽器不可見狀態(tài)下間隔低于1s的會變?yōu)?s,大于等于1s的會變成N+1s的間隔值?;鸷鼮g覽器下setTimeout的最小間隔時間會變?yōu)?s,大于等于1s的間隔不變。ie瀏覽器在不可見狀態(tài)前后的間隔時間不變。

    這個結(jié)論,我沒有驗證過,但看起來差異挺大,其中還提到了另外一個選擇,就是 requestAnimationFrame。

    window.requestAnimationFrame() 告訴瀏覽器——你希望執(zhí)行一個動畫,并且要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動畫。該方法需要傳入一個回調(diào)函數(shù)作為參數(shù),該回調(diào)函數(shù)會在瀏覽器下一次重繪之前執(zhí)行

    為了提高性能和電池壽命,因此在大多數(shù)瀏覽器里,當requestAnimationFrame() 運行在后臺標簽頁或者隱藏的 <iframe> 里時,requestAnimationFrame() 會被暫停調(diào)用以提升性能和電池壽命

    所以,ahooks 也提供了使用 requestAnimationFrame 進行模擬定時器處理的 hook,我們一起來看下。

    useRafInterval 和 useRafTimeout

    直接看 useRafInterval。(useRafTimeout 和 useRafInterval 類似,這里不展開細說)。

    function useRafInterval(
      fn: () => void,
      delay: number | undefined,
      options?: {
        immediate?: boolean;
      },
    ) {
      const immediate = options?.immediate;
      const fnRef = useLatest(fn);
      useEffect(() => {
        // 省略部分代碼...
        const timer = setRafInterval(() => {
          fnRef.current();
        }, delay);
        return () => {
          clearRafInterval(timer);
        };
      }, [delay]);
    }

    可以看到,跟前面的 useInterval 大部分代碼邏輯都是一樣的,只是定時使用了 setRafInterval 方法,清除定時器用了 clearRafInterval

    setRafInterval

    直接上代碼:

    const setRafInterval = function (callback: () => void, delay: number = 0): Handle {
      if (typeof requestAnimationFrame === typeof undefined) {
        // 如果不支持,還是使用 setInterval
        return {
          id: setInterval(callback, delay),
        };
      }
      // 開始時間
      let start = new Date().getTime();
      const handle: Handle = {
        id: 0,
      };
      const loop = () => {
        const current = new Date().getTime();
        // 當前時間 - 開始時間,大于設(shè)置的間隔,則執(zhí)行,并重置開始時間
        if (current - start >= delay) {
          callback();
          start = new Date().getTime();
        }
        handle.id = requestAnimationFrame(loop);
      };
      handle.id = requestAnimationFrame(loop);
      return handle;
    };

    首先是用 typeof 判斷進行兼容邏輯處理,假如不兼容,則兜底使用 setInterval。

    初始記錄一個 start 的時間。

    在 requestAnimationFrame 回調(diào)中,判斷現(xiàn)在的時間減去開始時間有沒有達到間隔,假如達到則執(zhí)行我們的 callback 函數(shù)。更新開始時間。

    clearRafInterval

    清除定時器。

    function cancelAnimationFrameIsNotDefined(t: any): t is NodeJS.Timer {
      return typeof cancelAnimationFrame === typeof undefined;
    }
    // 清除定時器
    const clearRafInterval = function (handle: Handle) {
      if (cancelAnimationFrameIsNotDefined(handle.id)) {
        return clearInterval(handle.id);
      }
      cancelAnimationFrame(handle.id);
    };

    假如不支持 cancelAnimationFrame API,則通過 clearInterval 清除,支持則直接使用 cancelAnimationFrame 清除。

    感謝各位的閱讀,以上就是“javascript定時器在頁面最小化時不執(zhí)行怎么實現(xiàn)”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對javascript定時器在頁面最小化時不執(zhí)行怎么實現(xiàn)這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI