<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          減少重復(fù)的請求,也許這個庫能幫到你

          共 6007字,需瀏覽 13分鐘

           ·

          2022-01-19 18:16

          大廠技術(shù)??高級前端??Node進階

          點擊上方?程序員成長指北,關(guān)注公眾號

          回復(fù)1,加入高級Node交流群

          如果你對這個庫感興趣,歡迎 Star 或提請 Issue ,也可以成為這個庫的貢獻者。(如果有人能幫我翻譯中轉(zhuǎn)英文檔或?qū)憸y試用例,我將感激不盡)

          并不是取消Promise,而是把多個相同的Promise變成一個! 該執(zhí)行的函數(shù)還是會執(zhí)行,還是會有返回值,但是不會再生成多余的Promise了。

          請想象下面兩個場景

          1

          有時候,在同一個頁面上,存在多個部分,如下圖所示。

          image.png

          而在這各個部分中又存在一些重復(fù)的數(shù)據(jù),例如綠色部分,他們實際上對應(yīng)的請求的是后端同一個內(nèi)容。

          這個時候,假如我們采取的是對模塊的每個組件塊都發(fā)起一次請求,很明顯,這三個可以共享返回值的請求重復(fù)了。

          對于這三個重復(fù)的請求,是否有辦法只發(fā)起一次請求,然后三個請求共享同一個返回值呢?

          2

          假設(shè)有一個組件提供局部刷新或者加載的功能。

          image.png

          有時候用戶點擊刷新的時候,因為手抖或者其它未知的原因,總之就是點了不止一下,可能點了好幾下,導(dǎo)致直接發(fā)送了好幾次請求。

          對于這好幾次請求,是否能夠進行整合,只發(fā)送了一次請求呢?

          once-init

          你當(dāng)然可以自己設(shè)計一個復(fù)雜的邏輯,封裝一個相對安全的組件。又或者,你可以試試 once-init ?

          github[1] npm[2]

          ![npm license](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/743b06903202404f850ce62f6c86ac6e~tplv-k3u1fbpfcp-watermark.awebp)[3] ![npm version](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/962d8f7868cb41ee81d1272600fe4a28~tplv-k3u1fbpfcp-watermark.awebp)[4]

          Promise Function Init Once, Use Everywhere.

          只會被初始化一次的 Promise 函數(shù)。

          第一次調(diào)用對象的時候會執(zhí)行 Promise 函數(shù)初始化,重復(fù)調(diào)用,初始化將不會再次執(zhí)行。

          同一個 Promise 不會在同一時間內(nèi)被執(zhí)行兩次。

          壓縮后大小

          承諾

          1. OnceInit 封裝的 Promise Function ,永遠不會在同一時間被執(zhí)行兩次。
          2. 如果上一個 Promise Function 沒有執(zhí)行完成就調(diào)用了下一個 Promise Function ,那么下一個 Promise Function 將共享上一個 Promise FunctionPromise。

          示例

          假設(shè)存在一個 axios Promise 請求,返回值類型為 number ,值為 777。

          const?requestNumber?=?async?()?=>?{
          ??const?res:?AxiosResponse<number>?=?await?axiosInstance.get("/api/number");
          ??return?res.data;
          };
          復(fù)制代碼

          你可以使用 oi 來封裝這個 Promise 函數(shù)

          const?oiInstance?=?oi(requestNumber);
          復(fù)制代碼

          現(xiàn)在,你可以在任何地方調(diào)用這個實例。

          init

          假設(shè)有兩個方法 functionAfunctionA,都需要發(fā)送這個請求。

          async?function?functionA()?{
          ??...
          ??const?res?=?await?oiInstance.init();
          ??...
          }

          async?function?functionB()?{
          ??...
          ??const?res?=?await?oiInstance.init();
          ??...
          }
          復(fù)制代碼

          而你需要在某個文件中,需要同時使用這兩個方法。

          async?function?functionC()?{
          ??await?functionA();
          ??await?functionB();
          }

          function?functionD()?{
          ??functionA();
          ??functionB();
          }
          復(fù)制代碼

          對于 functionC, 在第一次執(zhí)行 init 之后,oiInstance 將會保存 Promise 的執(zhí)行結(jié)果,此后再執(zhí)行 init ,將不會再發(fā)出 Promise 請求。

          對于 functionDapi 請求只會發(fā)送一次,functionAfunctionB 中的 res 都將等待同一個請求的返回值,不會發(fā)送重復(fù)的請求。

          target

          target 能同步獲取返回值。

          function?functionE()?{
          ??...
          ??const?res?=?oiInstance.target;
          ??...
          }
          復(fù)制代碼

          如果在獲取 target 之前已經(jīng)完成初始化,target 的值為 Promise 的返回值,否則,target 的值為 undefined 。例如,

          const?res?=?oiInstance.target;?//?undefined
          復(fù)制代碼
          await?oiInstance.init();

          const?res?=?oiInstance.target;?//?[Return?Value]?777
          復(fù)制代碼

          請注意,雖然是同步獲取,但 once-init 仍然會認為你此時需要發(fā)出請求,因此調(diào)用 target 屬性也會開始初始化。

          在下面這個例子中,我們假設(shè) api 的請求時長是 10s 。在下面這個例子里,請求在第一行的時候就已經(jīng)發(fā)出。

          const?res?=?oiInstance.target;?//?undefined
          /**?Promise?has?been?executed.?*/
          setTimeout(async?()?=>?{
          ??const?resAfter?=?oiInstance.target;?//?[Return?Value]?777
          ??const?intAffter?=?await?oiInstance.init();?//?[Return?Value]?777?,?Promise?will?not?be?executed?again.
          ??/**?Since?The?Promise?has?been?executed?before,?it?will?not?be?executed?again.?*/
          },?10001);
          復(fù)制代碼

          和同時先后同步執(zhí)行兩次 init 一樣,假如在獲取 init 之前訪問了 target 屬性,而 訪問 target 導(dǎo)致的 Promise 請求沒有結(jié)束的話,init 將直接等待上一個 Promise 結(jié)束并返回上一個 Promise 的返回值 。

          下面這個例子將會幫助你理解。

          const?res?=?oiInstance.target;?//?undefined
          setTimeout(async?()?=>?{
          ??const?resAfter?=?oiInstance.target;?//?undefined
          ??const?intAffter?=?await?oiInstance.init();?//?[Return?Value]?777
          ??/**?Since?The?Promise?has?been?executing?it?will?not?be?executing?again.??*/
          ??/**?After?About?8000ms,?The?Value?will?be?return?by?the?first?promise?done?*/
          },?2000);
          復(fù)制代碼

          這里的 init 將會等待上一個 Promise 函數(shù)執(zhí)行的返回值,由于 init 是在 200ms 之后才執(zhí)行的,所以它只需要再等待大約 800ms 就能獲得這個返回值了。

          defaultValue

          使用 target 屬性通常需要搭配默認值,而 oi 的第二個參數(shù)可以為你的 Promise 定義默認值。

          const?defaultValue?=?-1;
          const?oiInstance?=?oi(requestNumber,?defaultValue);

          const?ans?=?oiInstance.target;?//?-1
          復(fù)制代碼

          refresh

          你如果想要更新實例的值,則需要調(diào)用 refresh 。

          假設(shè)第一次加載的值是 777 ,而刷新之后的值是 888 。

          const?ans?=?await?oiInstance.init();?//?[Retrun?Value]?777
          const?ansAfterRefresh?=?await?oiInstance.refresh();?//?[Retrun?Value]?888
          復(fù)制代碼

          刷新之后,調(diào)用 inittarget 獲取的值會變成新的值。

          oiInstance.target;?//?undefined
          await?oiInstance.init();?//?[Promise?Retrun?Value]?777
          oiInstance.target;?//?777
          await?oiInstance.refresh();?//?[Promise?Retrun?Value]?888
          /**?Promise?will?not?be?exectued?*/
          oiInstance.target;?//?888
          await?oiInstance.init();?//?888
          復(fù)制代碼

          你可以直接使用 refresh 來執(zhí)行初始化,在初始化上,它和 init 的效果一致。

          oiInstance.target;?//?undefined
          await?oiInstance.refresh();?//?[Promise?Retrun?Value]?777
          oiInstance.target;?//?777
          await?oiInstance.refresh();?//?[Promise?Retrun?Value]?888
          oiInstance.target;?//?888
          復(fù)制代碼

          如果同步先后調(diào)用了兩次 refresh ,兩次 refresh 將等待同一個請求的返回值,不會發(fā)送重復(fù)的請求。

          async?function?functionA()?{
          ??console.log("A",?await?oiInstance.refresh());
          }
          async?function?functionB()?{
          ??console.log("B",?await?oiInstance.refresh());
          }
          functionA();?//?'A',?[Promise?Retrun?Value]?777
          functionB();?//?'B',?[Promise?Retrun?Value]?777
          /**?only?one?promise?is?executed?*/
          /**?functionA?and?functionB?share?A?same?promise?and?promise?return?value?*/
          復(fù)制代碼

          我們?nèi)匀患僭O(shè) api 請求的時長為 10s === 10000ms 。

          oiInstance.refresh();
          setTimeout(async?()?=>?{
          ??await?oiInstance.refresh();
          },?2000);
          /**?After?10000ms,?two?refresh?will?be?exected?at?the?same?time?*/
          復(fù)制代碼

          如果異步先后調(diào)用了兩次 refresh ,那么發(fā)送兩次請求。

          async?function?functionA()?{
          ??console.log("A",?await?oiInstance.refresh());
          }
          async?function?functionB()?{
          ??console.log("B",?await?oiInstance.refresh());
          }
          await?functionA();?//?'A',?[Promise?Retrun?Value]?777
          await?functionB();?//?'B',?[Promise?Retrun?Value]?888
          /**?Two?different?promises?were?executed?*/
          復(fù)制代碼

          如果你覺得邏輯太過復(fù)雜,那請至少要記住一點,OnceInit 封裝的 Promise Function ,永遠不會在同一時間被執(zhí)行兩次。

          除此之外,once-init 還提供了其它的 api ,以滿足更多的需求,但以上是它的主要功能。更多信息請查看 once-init 的 github[5] 。

          HELP

          我還將把發(fā)布一個 Vue3-Composition Api 的版本。(預(yù)定中)

          export?abstract?class?RefOnceInit?extends?OnceInit<
          ??Ref,
          ??G
          >?{
          ??loading?=?ref(false);
          ??protected?abstract?factory(raw:?G,?observe:?Ref):?void;
          ??constructor(defaultValue?:?T)?{
          ????const?refed?=?ref();
          ????refed.value?=?defaultValue;
          ????super(refed);
          ????this.onLoading((event)?=>?{
          ??????this.loading.value?=?event;
          ????});
          ??}
          }
          復(fù)制代碼

          這樣 RefOnceInit 就是一個響應(yīng)式的對象。關(guān)于 OnceInit 類請查看源碼。

          當(dāng)請求完成的時候,就能引發(fā)頁面 UI 的變化。


          關(guān)于本文

          來源:Xmo

          https://juejin.cn/post/7046667393405304868

          Node 社群


          我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。


          ???“分享、點贊、在看” 支持一波??

          瀏覽 34
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲电影第二页 | 亚洲高清视频不卡 | 欧美日韩在线免费看 | 狠狠干综合 | 国产黄色在线播放 |