<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ù)能幫到你

          共 9912字,需瀏覽 20分鐘

           ·

          2022-01-11 20:50

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

          回復(fù)加群,加入前端Q技術(shù)交流群


          如果你對(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ì)開始初始化。

          在下面這個(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<T, G = T> extends OnceInit<
            Ref<T | undefined>,
            G
          > {
            loading = ref<boolean>(false);
            protected abstract factory(raw: G, observe: Ref<T | undefined>): void;
            constructor(defaultValue?: T) {
              const refed = ref<T>();
              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


          往期推薦


          對(duì)話Svelte未來(lái),Rust 編譯器?構(gòu)建大型應(yīng)用?
          2022年如何成為一名優(yōu)秀的大前端Leader
          大漠老師:2022 年的 CSS,到底有哪些特性

          最后


          • 歡迎加我微信,拉你進(jìn)技術(shù)群,長(zhǎng)期交流學(xué)習(xí)...

          • 歡迎關(guān)注「前端Q」,認(rèn)真學(xué)前端,做個(gè)專業(yè)的技術(shù)人...

          點(diǎn)個(gè)在看支持我吧
          瀏覽 31
          點(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>
                  狠狠7777 | 俺去精品在线 | 夜色色综合| AAA片网站| 狠狠地操|