成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

useEffect支持async及await如何運用

3403771864 / 523人閱讀

       背景

  在使用useEffect中用啦回調(diào)函數(shù)中使用 async...await... 這時候就會報錯。

1.png

  上面代碼可以看到,在報錯,effect function 應(yīng)該返回一個銷毀函數(shù)(effect:是指return返回的cleanup函數(shù)),如果 useEffect 第一個參數(shù)傳入 async,返回值則變成了 Promise,結(jié)果就是會導(dǎo)致 react 在調(diào)用銷毀函數(shù)的時候報錯。

  React 為什么要這么做?

  useEffect 作為 Hooks 中一個很重要的 Hooks,它能夠讓你在函數(shù)組件中執(zhí)行副作用操作。 也能夠完成之前 Class Component 中的生命周期的職責。它返回的函數(shù)的執(zhí)行時機如下:

  首次渲染不會進行清理,會在下一次渲染,清除上一次的副作用。

  卸載階段也會執(zhí)行清除操作。

  不管怎樣,返回值是異步,這樣我們無法預(yù)知代碼的執(zhí)行情況,很容易出現(xiàn)難以定位的 Bug。所以 React 就直接限制了不能 useEffect 回調(diào)函數(shù)中不能支持 async...await...

  useEffect 怎么支持 async...await...

  竟然 useEffect 的回調(diào)函數(shù)不能使用 async...await,那我直接在它內(nèi)部使用。

  做法一:創(chuàng)建一個異步函數(shù)(async...await 的方式),然后執(zhí)行該函數(shù)。

  useEffect(() => {
  const asyncFun = async () => {
  setPass(await mockCheck());
  };
  asyncFun();
  }, []);

  做法二:也可以使用 IIFE,如下所示:

  useEffect(() => {
  (async () => {
  setPass(await mockCheck());
  })();
  }, []);

  自定義 hooks

  現(xiàn)在知道解決方法,我們完全可以將其封裝成一個 hook,是不是更優(yōu)雅?,F(xiàn)在看下 ahooks 的 useAsyncEffect,它支持所有的異步寫法,包括 generator function。

  思路跟上面一樣,入?yún)⒏?useEffect 一樣,一個回調(diào)函數(shù)(不過這個回調(diào)函數(shù)支持異步),另外一個依賴項 deps。內(nèi)部還是 useEffect,將異步的邏輯放入到它的回調(diào)函數(shù)里面。

  function useAsyncEffect(
  effect: () => AsyncGenerator<void, void, void> | Promise<void>,
  // 依賴項
  deps?: DependencyList,
  ) {
  // 判斷是 AsyncGenerator
  function isAsyncGenerator(
  val: AsyncGenerator<void, void, void> | Promise<void>,
  ): val is AsyncGenerator<void, void, void> {
  // Symbol.asyncIterator: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator
  // Symbol.asyncIterator 符號指定了一個對象的默認異步迭代器。如果一個對象設(shè)置了這個屬性,它就是異步可迭代對象,可用于for await...of循環(huán)。
  return isFunction(val[Symbol.asyncIterator]);
  }
  useEffect(() => {
  const e = effect();
  // 這個標識可以通過 yield 語句可以增加一些檢查點
  // 如果發(fā)現(xiàn)當前 effect 已經(jīng)被清理,會停止繼續(xù)往下執(zhí)行。
  let cancelled = false;
  // 執(zhí)行函數(shù)
  async function execute() {
  // 如果是 Generator 異步函數(shù),則通過 next() 的方式全部執(zhí)行
  if (isAsyncGenerator(e)) {
  while (true) {
  const result = await e.next();
  // Generate function 全部執(zhí)行完成
  // 或者當前的 effect 已經(jīng)被清理
  if (result.done || cancelled) {
  break;
  }
  }
  } else {
  await e;
  }
  }
  execute();
  return () => {
  // 當前 effect 已經(jīng)被清理
  cancelled = true;
  };
  }, deps);
  }

  async...await 其實之前就有說道,重點看看實現(xiàn)中變量 cancelled 的實現(xiàn)的功能。 它的作用是中斷執(zhí)行。

  通過 yield 語句可以增加一些檢查點,如果發(fā)現(xiàn)當前 effect 已經(jīng)被清理,會停止繼續(xù)往下執(zhí)行。

  現(xiàn)在我們試想,用戶頻繁的操作,可能現(xiàn)在這一輪操作 a 執(zhí)行還沒完成,就已經(jīng)開始開始下一輪操作 b。這個時候,操作 a 的邏輯已經(jīng)失去了作用了,那么我們就可以停止往后執(zhí)行,直接進入下一輪操作 b 的邏輯執(zhí)行。這個 cancelled 就是用來取消當前正在執(zhí)行的一個標識符。

  還可以支持 useEffect 的清除機制么?

  可以看到上面的 useAsyncEffect,內(nèi)部的 useEffect 返回函數(shù)只返回了如下:

  return () => {
  // 當前 effect 已經(jīng)被清理
  cancelled = true;
  };

  上面其實就是說明,在通過 useAsyncEffect 沒有 useEffect 返回函數(shù)中執(zhí)行清除副作用的功能。

  你猜想將 effect(useAsyncEffect的回調(diào)函數(shù))的結(jié)果,放入到 useAsyncEffect 中不就可以了?

  實現(xiàn)最終類似如下:

  function useAsyncEffect(effect: () => Promise<void | (() => void)>, dependencies?: any[]) {
  return useEffect(() => {
  const cleanupPromise = effect()
  return () => { cleanupPromise.then(cleanup => cleanup && cleanup()) }
  }, dependencies)
  }

  上面方法很多大神讀贊成:

2.png

  上面不是延遲機制,是一種取消機制。否則,在鉤子已經(jīng)被取消之后,回調(diào)函數(shù)仍然有機會對外部狀態(tài)產(chǎn)生影響。他的實現(xiàn)和例子我也貼一下,跟 useAsyncEffect 其實思路是一樣的,如下:

  實現(xiàn):

  function useAsyncEffect(effect: (isCanceled: () => boolean) => Promise<void>, dependencies?: any[]) {
  return useEffect(() => {
  let canceled = false;
  effect(() => canceled);
  return () => { canceled = true; }
  }, dependencies)
  }

  Demo:

  useAsyncEffect(async (isCanceled) => {
  const result = await doSomeAsyncStuff(stuffId);
  if (!isCanceled()) {
  // TODO: Still OK to do some effect, useEffect hasn't been canceled yet.
  }
  }, [stuffId]);

  其實歸根結(jié)底,我們的清除機制不應(yīng)該依賴于異步函數(shù),否則很容易出現(xiàn)難以定位的 bug。

  總結(jié)與思考

  在代碼運行中由于 useEffect 是在函數(shù)式組件中承擔執(zhí)行副作用操作的職責,它的返回值的執(zhí)行操作應(yīng)該是可以預(yù)期的,而不能是一個異步函數(shù),所以不支持回調(diào)函數(shù) async...await 的寫法。

  我們可以將 async...await 的邏輯封裝在 useEffect 回調(diào)函數(shù)的內(nèi)部,這就是 ahooks useAsyncEffect 的實現(xiàn)思路,而且它的范圍更加廣,它支持的是所有的異步函數(shù),包括generator function。

      本文內(nèi)容已結(jié)束,歡迎閱讀更多精彩內(nèi)容。


文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/128371.html

相關(guān)文章

  • 在 React Hooks 中如何請求數(shù)據(jù)?

    摘要:現(xiàn)在,請求數(shù)據(jù)和查詢參數(shù)兩個相互獨立,但是我們需要像一個辦法希望他們耦合起來,只獲取輸入框輸入的參數(shù)指定的話題文章。好了,現(xiàn)在一旦你改變輸入框內(nèi)容,數(shù)據(jù)就會重新獲取。 showImg(https://segmentfault.com/img/remote/1460000018652592?w=1024&h=683); 通過這個教程,我想告訴你在 React 中如何使用 state 和 ...

    snowell 評論0 收藏0
  • 【譯】如何在React Hooks中獲取數(shù)據(jù)?

    摘要:在這種情況下,如果狀態(tài)發(fā)生變化,將再次運行以從獲取數(shù)據(jù)。你可以在內(nèi)做到在表單中獲取數(shù)據(jù)到目前為止,我們只有和按鈕的組合?,F(xiàn)在,在獲取數(shù)據(jù)時,可以使用向函數(shù)發(fā)送信息。例如,在成功請求的情況下,用于設(shè)置新狀態(tài)對象的數(shù)據(jù)。 原文鏈接: https://www.robinwieruch.de/r... 在本教程中,我想通過state和effect hook來像你展示如何用React Hook...

    habren 評論0 收藏0
  • 「每日一瞥

    摘要:首先,我們需要一個基本框架來處理表單域變化和表格提交。最起碼我們需要提供一個來告訴如果用戶還沒有對表單域進行改動,就不必展示錯誤。我們需要一個來標識用戶已嘗試提交表單,還需要來標識表單是否正在提交以及每個表單域是否正在進行異步校驗。 showImg(https://segmentfault.com/img/remote/1460000017516912?w=1200&h=630); ...

    XboxYan 評論0 收藏0
  • React Hooks 入門(2019)

    摘要:到目前為止,表達這種流程的基本形式是課程。按鈕依次響應(yīng)并更改獲取更新的文本。事實證明不能從返回一個??梢栽诮M件中使用本地狀態(tài),而無需使用類。替換了提供統(tǒng)一,和。另一方面,跟蹤中的狀態(tài)變化確實很難。 備注:為了保證的可讀性,本文采用意譯而非直譯。 在這個 React鉤子 教程中,你將學(xué)習(xí)如何使用 React鉤子,它們是什么,以及我們?yōu)槭裁催@樣做! showImg(https://segm...

    GitCafe 評論0 收藏0
  • 解析React useEffect支持async function示例

      useEffect是很常見的,現(xiàn)在寫的是十分需求的。  useEffect(async()=>{   awaitgetPoiInfo();//請求數(shù)據(jù)   },[]);  可是React 卻無法支持這樣做,就是因為 effect function 應(yīng)該返回一個銷毀函數(shù)(effect:是指return返回的cleanup函數(shù)),如果 useEffect 第一個參數(shù)傳入 async,返回值則...

    3403771864 評論0 收藏0

發(fā)表評論

0條評論

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