<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ù)的請(qǐng)求,也許這個(gè)庫(kù)能幫到你

          共 6009字,需瀏覽 13分鐘

           ·

          2022-01-08 17:52

          點(diǎn)擊上方?前端瓶子君,關(guān)注公眾號(hào)

          回復(fù)算法,加入前端編程面試算法每日一題群

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

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

          請(qǐng)想象下面兩個(gè)場(chǎng)景

          1

          有時(shí)候,在同一個(gè)頁(yè)面上,存在多個(gè)部分,如下圖所示。

          image.png

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

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

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

          2

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

          image.png

          有時(shí)候用戶點(diǎn)擊刷新的時(shí)候,因?yàn)槭侄痘蛘咂渌粗脑颍傊褪屈c(diǎn)了不止一下,可能點(diǎn)了好幾下,導(dǎo)致直接發(fā)送了好幾次請(qǐng)求。

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

          once-init

          你當(dāng)然可以自己設(shè)計(jì)一個(gè)復(fù)雜的邏輯,封裝一個(gè)相對(duì)安全的組件。又或者,你可以試試 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.

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

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

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

          壓縮后大小

          承諾

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

          示例

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

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

          你可以使用 oi 來(lái)封裝這個(gè) Promise 函數(shù)

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

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

          init

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

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

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

          而你需要在某個(gè)文件中,需要同時(shí)使用這兩個(gè)方法。

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

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

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

          對(duì)于 functionD, api 請(qǐng)求只會(huì)發(fā)送一次,functionAfunctionB 中的 res 都將等待同一個(gè)請(qǐng)求的返回值,不會(huì)發(fā)送重復(fù)的請(qǐng)求。

          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ù)制代碼

          請(qǐng)注意,雖然是同步獲取,但 once-init 仍然會(huì)認(rèn)為你此時(shí)需要發(fā)出請(qǐng)求,因此調(diào)用 target 屬性也會(huì)開(kāi)始初始化。

          在下面這個(gè)例子中,我們假設(shè) api 的請(qǐng)求時(shí)長(zhǎng)是 10s 。在下面這個(gè)例子里,請(qǐng)求在第一行的時(shí)候就已經(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ù)制代碼

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

          下面這個(gè)例子將會(huì)幫助你理解。

          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 將會(huì)等待上一個(gè) Promise 函數(shù)執(zhí)行的返回值,由于 init 是在 200ms 之后才執(zhí)行的,所以它只需要再等待大約 800ms 就能獲得這個(gè)返回值了。

          defaultValue

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

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

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

          refresh

          你如果想要更新實(shí)例的值,則需要調(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 獲取的值會(huì)變成新的值。

          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 來(lái)執(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 將等待同一個(gè)請(qǐng)求的返回值,不會(huì)發(fā)送重復(fù)的請(qǐng)求。

          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 請(qǐng)求的時(shí)長(zhǎng)為 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ā)送兩次請(qǐng)求。

          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ù)制代碼

          如果你覺(jué)得邏輯太過(guò)復(fù)雜,那請(qǐng)至少要記住一點(diǎn),OnceInit 封裝的 Promise Function ,永遠(yuǎn)不會(huì)在同一時(shí)間被執(zhí)行兩次

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

          HELP

          我還將把發(fā)布一個(gè) 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 就是一個(gè)響應(yīng)式的對(duì)象。關(guān)于 OnceInit 類請(qǐng)查看源碼。

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


          關(guān)于本文

          來(lái)源:Xmo

          https://juejin.cn/post/7046667393405304868

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會(huì)很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對(duì)你有幫助,在看」是最大的支持
          ?》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持


          瀏覽 44
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  婷婷亚洲视频 | A∨日本精品免费 | 精品欧美日韩一区二区三区播放 | 草久久| 国产777 |