国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

演示當定時器在頁面最小化時無法執行

3403771864 / 738人閱讀

  我們講述的是關于 ahooks 源碼系列文章的第七篇,總結主要講述下面幾點:

  鞏固 React hooks 的理解。

  學習如何抽象自定義 hooks。構建屬于自己的 React hooks 工具庫。

  培養閱讀學習源碼的習慣,工具庫是一個對源碼閱讀不錯的選擇。

  注:本系列對 ahooks 的源碼解析是基于v3.3.13。自己 folk 了一份源碼,主要是對源碼做了一些解讀,可見詳情。

  現在進入主題:定時器。

  useInterval 和 useTimeout,它們的功能對應的是 setInterval 和 setTimeout,那對比后者有什么優勢?

  先看useInterval,代碼如下所示:

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

  跟 setInterval 的區別如下:

  可以支持第三個參數,通過 immediate 能夠立即執行我們的定時器。這樣就可以在變更 delay 的時候,會自動清除舊的定時器,并同時啟動新的定時器。

  通過 useEffect 的返回清除機制,開發者不需要關注清除定時器的邏輯,避免內存泄露問題。記住這個點是在開發中很容易忽略的。

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

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

  setTimeout 和 setInterval 的問題

  首先,setTimeout 和 setInterval 作為事件循環中宏任務的“兩大主力”,要知道它的執行時機無法和我們預期一樣準確的,它要做的就是等待,在前面任務的執行。比如下面的 setTimeout 的第二個參數設置為 0,并不會立即執行。

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

  另外還有一種情況,setTimeout 和 setInterval 在瀏覽器不可見的時候(比如最小化的時候),不同的瀏覽器中設置不同的時間間隔的時候,得出的表現就不一樣。根據當瀏覽器切換到其他標簽頁或者最小化時,你的js定時器還準時嗎?這篇文章的實踐結論如下:

  當谷歌瀏覽器中,在頁面處于不可見狀態時,setInterval 的最小間隔時間會被限制為 1s。可在火狐瀏覽器的 setInterval 和谷歌特性一致,但是 ie 瀏覽器沒有對不可見狀態時的 setInterval 進行性能優化,不可見前后間隔時間不變。

  在谷歌瀏覽器中,setTimeout在瀏覽器不可見狀態下間隔低于1s的會變為1s,大于等于1s的會變成N+1s的間隔值。火狐瀏覽器下setTimeout的最小間隔時間會變為1s,大于等于1s的間隔不變。ie瀏覽器在不可見狀態前后的間隔時間不變。

  總結上面看來,差異不小,就要換個,那就是 requestAnimationFrame。

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

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

  所以,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();
  // 當前時間 - 開始時間,大于設置的間隔,則執行,并重置開始時間
  if (current - start >= delay) {
  callback();
  start = new Date().getTime();
  }
  handle.id = requestAnimationFrame(loop);
  };
  handle.id = requestAnimationFrame(loop);
  return handle;
  };

  首先是用 typeof 判斷進行兼容邏輯處理,出現兼容,那就需要setInterval出場。

  初始記錄一個 start 的時間。

  在 requestAnimationFrame 回調中,判斷現在的時間減去開始時間有沒有達到間隔,假如達到則執行我們的 callback 函數。更新開始時間。

  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);
  };

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

  復盤與總結

  我們開發者對于定時器,要記得及時清楚,這里建議用seEffect返回清除副作用函數這個特性,我們可以將這類邏輯一起封裝到 hook 中,怎么樣是不是很方便。

  還有就是在希望在頁面不可見的時候,不執行定時器,可以選擇 useRafInterval 和 useRafTimeout,其內部是使用requestAnimationFrame進行實現。

  有關定時器在頁面最小化時不執行實現示例的詳細內容已敘述完,請大家多多關注后續更多精彩內容。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/128190.html

相關文章

  • 《高性能javascript》閱讀摘要

    摘要:當執行上下文被創建時,它的作用域鏈初始化為當前運行函數的屬性中的對象。該過程搜索執行環境的作用域鏈,查找同名的標識符。搜索實例成員比從字面量或局部變量中讀取數據代價更高,再加上遍歷原型鏈帶來的開銷,這讓性能問題更為嚴重。 最近在閱讀這本Nicholas C.Zakas(javascript高級程序設計作者)寫的最佳實踐、性能優化類的書。記錄下主要知識。 加載和執行 腳本位置 放在中的...

    duan199226 評論0 收藏0
  • 《高性能javascript》閱讀摘要

    摘要:當執行上下文被創建時,它的作用域鏈初始化為當前運行函數的屬性中的對象。該過程搜索執行環境的作用域鏈,查找同名的標識符。搜索實例成員比從字面量或局部變量中讀取數據代價更高,再加上遍歷原型鏈帶來的開銷,這讓性能問題更為嚴重。 最近在閱讀這本Nicholas C.Zakas(javascript高級程序設計作者)寫的最佳實踐、性能優化類的書。記錄下主要知識。 加載和執行 腳本位置 放在中的...

    afishhhhh 評論0 收藏0
  • 瀏覽器知識

    摘要:瀏覽器的渲染進程是多線程的。異步請求線程在在連接后是通過瀏覽器新開一個線程請求將檢測到狀態變更時,如果設置有回調函數,異步線程就產生狀態變更事件,將這個回調再放入事件隊列中。 [TOC] 瀏覽器進程線程 區分線程和進程 **- 什么是進程** 狹義定義:進程是正在運行的程序的實例(an instance of a computer program that is being exe...

    Pluser 評論0 收藏0

發表評論

0條評論

3403771864

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<