<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>

          封裝 axios 取消重復(fù)請(qǐng)求

          共 5400字,需瀏覽 11分鐘

           ·

          2021-01-05 10:42

          編者按:本文作者舒麗琦,奇舞團(tuán)前端開發(fā)工程師

          在我們web開發(fā)過(guò)程中,很多地方需要我們?nèi)∠貜?fù)的請(qǐng)求。但是哪種場(chǎng)合需要我們?nèi)∠兀课覀內(nèi)绾稳∠兀繋е@些問(wèn)題我們閱讀本文。

          閱讀完本文,你將了解以下內(nèi)容:

          • 需要取消重復(fù)請(qǐng)求的場(chǎng)景

          • 我們?nèi)绾稳∠貜?fù)請(qǐng)求

          • axios如何取消重復(fù)的請(qǐng)求

          • 封裝axios

          • 如何給開源的項(xiàng)目提供源碼

          • 如何在本地調(diào)試npm包

          提出問(wèn)題

          最近做的項(xiàng)目中,用的用戶經(jīng)常遇到這樣的問(wèn)題:

          • 用戶頻繁切換篩選條件去請(qǐng)求數(shù)據(jù),初次的篩選條件數(shù)據(jù)量大。用的時(shí)間比較多。后面的篩選條件的數(shù)據(jù)量小。導(dǎo)致后面請(qǐng)求的數(shù)據(jù)先返回。內(nèi)容先顯示在頁(yè)面上。但是等一段時(shí)間,初次(或者前面)的請(qǐng)求數(shù)據(jù)返回了, 會(huì)覆蓋后面的請(qǐng)求的數(shù)據(jù)。這就導(dǎo)致了篩選條件和內(nèi)容不一致的情況。

          • 用戶點(diǎn)擊了一次提交按鈕,接口沒(méi)有很快響應(yīng),導(dǎo)致頁(yè)面沒(méi)辦法做邏輯語(yǔ)句判斷的提示。用戶覺(jué)得可能沒(méi)提交上,便會(huì)快速又點(diǎn)了按鈕幾次。如果后端沒(méi)有去重的判斷,就會(huì)導(dǎo)致數(shù)據(jù)中有很多條重復(fù)的數(shù)據(jù)。

          這些問(wèn)題給用戶的體驗(yàn)是很不友好的。那么取消無(wú)用的請(qǐng)求是很有必要的。

          解決思路

          我們用的請(qǐng)求庫(kù)是axios。那么我們可以在請(qǐng)求的時(shí)候攔截請(qǐng)求判斷當(dāng)前的請(qǐng)求是否重復(fù),如果重復(fù)我們就取消當(dāng)前的請(qǐng)求。大致的實(shí)現(xiàn)過(guò)程如下:

          我們把目前處于pending的請(qǐng)求存儲(chǔ)(假如我們放在一個(gè)數(shù)組)起來(lái)。每個(gè)請(qǐng)求發(fā)送之前我們都要判斷當(dāng)前這個(gè)請(qǐng)求是否已經(jīng)存在于這個(gè)數(shù)組。如果存在,說(shuō)明請(qǐng)求重復(fù)了,我們就在數(shù)組中找到重復(fù)的請(qǐng)求并且取消。如果不存在,說(shuō)明這個(gè)請(qǐng)求不是重復(fù)的,正常發(fā)送并且把這個(gè)請(qǐng)求api添加在數(shù)據(jù)中,等請(qǐng)求結(jié)束之后刪除數(shù)組中的這個(gè)api。

          我們這個(gè)解決思路有了,但是axios如何取消請(qǐng)求的呢?我們先來(lái)了解下

          axios 如何取消請(qǐng)求

          查看axios文檔發(fā)現(xiàn)axios提供了兩種取消請(qǐng)求的方法(http://www.axios-js.com/zh-cn/docs/#%E5%8F%96%E6%B6%88)

          • 第一種方法

            通過(guò)axios.CancelToken.source生成取消令牌token和取消方法cancel

            const?CancelToken?=?axios.CancelToken;

            const?source?=?CancelToken.source();


            axios.get('/user/12345',?{

            ??cancelToken:?source.token

            }).catch(function(thrown)?{

            ??if?(axios.isCancel(thrown))?{

            ????console.log('Request canceled',?thrown.message);

            ??}?else?{

            ????// 處理錯(cuò)誤

            ??}

            });


            axios.post('/user/12345',?{

            ??name:?'new name'

            },?{

            ??cancelToken:?source.token

            })


            // 取消請(qǐng)求 (消息參數(shù)是可選的)

            source.cancel('Operation canceled by the user.');


          • 第二種方式

            通過(guò)傳遞一個(gè) executor 函數(shù)到 CancelToken 的構(gòu)造函數(shù)來(lái)創(chuàng)建 cancel token

            const?CancelToken?=?axios.CancelToken;

            let?cancel;


            axios.get('/user/12345',?{

            ??cancelToken:?new?CancelToken(function?executor(c)?{

            ????// executor 函數(shù)接收一個(gè) cancel 函數(shù)作為參數(shù)

            ????cancel?=?c;

            ??})

            });


            // 取消請(qǐng)求

            cancel();


          封裝axios

          解決取消請(qǐng)求的思路有了,取消請(qǐng)求的辦法也有了,那么剩下的就是封裝了

          由于同事之前已經(jīng)封裝了axios——very-axios(https://github.com/verymuch/very-axios) (基于 axios 進(jìn)行二次封裝,更簡(jiǎn)單、更統(tǒng)一地使用 axios)。那么我們就這個(gè)基礎(chǔ)上提一個(gè)pr吧。那么從現(xiàn)在開始我們就一步一步的來(lái)實(shí)現(xiàn),這個(gè)過(guò)程包含了【如何給開源的項(xiàng)目貢獻(xiàn)代碼】【如何在本地調(diào)試npm】如果已經(jīng)了解的同學(xué)可以直接略過(guò)。

          準(zhǔn)備工作

          由于同事已經(jīng)封裝了axios并且已經(jīng)開源了。那么我貢獻(xiàn)代碼的方式主要有兩種:

          • 代碼倉(cāng)庫(kù)的管理者給我們添加這個(gè)倉(cāng)庫(kù)的寫入權(quán)限,如果這樣,我們就可以直接提push。

          • 如果我們沒(méi)有權(quán)限(大多數(shù)情況)。我們使用經(jīng)典的fork & pull request 的方式來(lái)提交代碼。

          我們采用的第二種方式。我們?nèi)?very-axios(https://github.com/verymuch/very-axios) 把代碼fork到自己的倉(cāng)庫(kù)(如果你還沒(méi)有自己的github,需要自己注冊(cè)下哦)。


          那么你回到自己的github倉(cāng)庫(kù)下面就會(huì)看有一個(gè)一摸一樣的項(xiàng)目


          那么我們現(xiàn)在就可以git clone這個(gè)倉(cāng)庫(kù)的代碼到本地,新建branch進(jìn)行開發(fā),就比如我新建了一個(gè)這樣的branch:

          現(xiàn)在已經(jīng)有本地的代碼了,但是我們?nèi)绾伪镜鼗{(diào)試npm包呢?那就需要npm link

          首先在我們要修改的npm 包中npm link


          之后我們會(huì)得到

          /Users/shuliqi/.nvm/versions/node/v12.17.0/lib/node_modules/very-axios?->?/Users/shuliqi/study/axios/very-axios

          這意思就是我們把very-axios鏈接到全局的node_modules

          然后我們進(jìn)入我們my-project-of-axios 目錄下面執(zhí)行npm link very-axios 如圖:

          這意思就是very-axios被安裝在my-project-of-axios 下面了。very-axios的修改都會(huì)同步到my-project-of-axios。就實(shí)現(xiàn)本地測(cè)試了。

          我們?cè)?span style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;border-width: 1px;border-style: solid;border-color: rgb(225, 225, 232);font-size: 12px;font-family: monospace;color: rgb(221, 17, 68);background-color: rgb(247, 247, 249);border-radius: 2px;word-break: break-all;">my-project-of-axios中的HelloWorld.vue文件中做列子。

          如果這里看的不是很懂的同學(xué)可以看看這兩篇文章:如何在本地調(diào)試npm包(https://github.com/allenGKC/Blog/issues/13)。如何使用 GitHub Flow 給開源項(xiàng)目貢獻(xiàn)代碼(https://juejin.im/post/6844903636863041550)


          開始封裝

          準(zhǔn)備工作完成了, 那我們開始封裝的事情。根據(jù)我們之前的思路。我們采用axios 如何取消請(qǐng)求的第一種方式。

          聲明一個(gè)Map。用來(lái)存儲(chǔ)每個(gè)請(qǐng)求的 標(biāo)識(shí) 和 取消的函數(shù)

          // 存儲(chǔ)每個(gè)請(qǐng)求的標(biāo)識(shí)和取消的函數(shù)

          this.pendingAjax?=?new?Map();

          自定一個(gè)字段來(lái)讓用戶自己決定是否需要取消重復(fù)的請(qǐng)求

          // 是否取消重復(fù)的請(qǐng)求

          cancelDuplicated?=?false,

          自定一個(gè)字段來(lái)讓用戶是否有全局的統(tǒng)一的設(shè)置重復(fù)標(biāo)識(shí)的函數(shù)。如果沒(méi)有設(shè)置全局的統(tǒng)一的函數(shù),則默認(rèn)是請(qǐng)求的methodurl作為重復(fù)的標(biāo)識(shí)

          // 生成重復(fù)標(biāo)識(shí)的方式

          duplicatedKeyFn,

          this.duplicatedKeyFn?=?isFunction(duplicatedKeyFn)???duplicatedKeyFn?:?(config)?=>?`${config.method}${config.url}`;

          添加請(qǐng)求

          /**

          ?* 將請(qǐng)求添加到pendingAjax

          ?* @param {Object} config

          ?*/

          addPendingAjax(config)?{

          ??//?是否需要取消重復(fù)的請(qǐng)求

          ??if?(!this.cancelDuplicated)?return

          ??const?veryConfig?=?config.veryConfig?||?{};

          ??const?duplicatedKey?=?JSON.stringify({

          ????duplicatedKey:?veryConfig.duplicatedKey?||?this.duplicatedKeyFn(config),

          ????type:?REQUEST_TYPE.DUPLICATED_REQUEST,

          ??});

          ??config.cancelToken?=?config.cancelToken?||?new?axios.CancelToken((cancel)?=>?{

          ????// 如果pendingAjax中不存在當(dāng)前請(qǐng)求,添加進(jìn)去

          ????if?(duplicatedKey?&&?!this.pendingAjax.has(duplicatedKey))?{

          ??????this.pendingAjax.set(duplicatedKey,?cancel);

          ????}

          ??});

          }

          這里面我們可以使用duplicatedKey字段來(lái)讓用戶對(duì)單一請(qǐng)求自定義重復(fù)的標(biāo)識(shí)。或者可以使用一個(gè)函數(shù)duplicatedKeyFn統(tǒng)一的讓用戶自定義重復(fù)的標(biāo)識(shí)

          刪除請(qǐng)求

          /**

          ???* 從pendingAjax中刪除請(qǐng)求

          ???* @param {Object} config

          ???*/

          ??removePendingAjax(config)?{

          ????//?是否需要取消重復(fù)的請(qǐng)求

          ????if?(!this.cancelDuplicated)?return

          ????const?veryConfig?=?config.veryConfig?||?{};

          ????const?duplicatedKey?=?JSON.stringify({

          ??????duplicatedKey:?veryConfig.duplicatedKey?||?this.duplicatedKeyFn(config),

          ??????type:?REQUEST_TYPE.DUPLICATED_REQUEST,

          ????});

          ????// 如果pendingAjax中存在當(dāng)前請(qǐng)求, 取消當(dāng)前請(qǐng)求并將其刪除

          ????if?(duplicatedKey?&&?this.pendingAjax.has(duplicatedKey))?{

          ??????const?cancel?=?this.pendingAjax.get(duplicatedKey);

          ??????cancel(duplicatedKey);

          ??????this.pendingAjax.delete(duplicatedKey);

          ????}

          ??}

          封裝好了, 我們?cè)谀睦锸褂媚兀靠隙ㄊ窃谡?qǐng)求開始之前和請(qǐng)求完成之后使用。

          在請(qǐng)求之前

          // 攔截請(qǐng)求

          this.axios.interceptors.request.use((config)?=>?{

          ??//?在請(qǐng)求開始之前檢查先前的請(qǐng)求

          ??this.removePendingAjax(config);

          ??// 將當(dāng)前請(qǐng)求添加到pendingAjax

          ??this.addPendingAjax(config);

          ??// ...

          });

          在請(qǐng)求完成之后去掉該請(qǐng)求

          // 攔截響應(yīng)

          this.axios.interceptors.response.use(response?=>?{

          ??removePending(response)

          ??return?response

          },?error?=>?{

          ??// ...

          })

          到現(xiàn)在已經(jīng)完成了該有的功能, 但是取消請(qǐng)求的錯(cuò)誤我們不該返回給用戶。所以:

          (err)?=>?{

          //?類型是否為重復(fù)請(qǐng)求

          let?isDuplicatedType;

          try?{

          ??const?errorType?=?(JSON.parse(error.message)?||?{}).type

          ??isDuplicatedType?=?errorType?===?REQUEST_TYPE.DUPLICATED_REQUEST;

          }?catch?(error)?{

          ??isDuplicatedType?=?false

          }

          if?(isDuplicatedType)?return;

          }

          我們?cè)谡?qǐng)求完成之后的err里面做一個(gè)判斷,判斷如果當(dāng)前請(qǐng)求是取消的類型,我們就不返回給用戶錯(cuò)誤的提示信息。

          總結(jié)

          至此,完成了我們的封裝。完成的pr地址:(https://github.com/verymuch/very-axios/pull/1)。本文測(cè)試npm包的項(xiàng)目地址:(https://github.com/shuliqi/my-project-of-axios)

          ??愛心三連擊

          1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的點(diǎn)贊在看是我創(chuàng)作的動(dòng)力。

          2.關(guān)注公眾號(hào)程序員成長(zhǎng)指北,回復(fù)「1」加入高級(jí)前端交流群!「在這里有好多 前端?開發(fā)者,會(huì)討論?前端 Node 知識(shí),互相學(xué)習(xí)」!

          3.也可添加微信【ikoala520】,一起成長(zhǎng)。

          “在看轉(zhuǎn)發(fā)”是最大的支持

          瀏覽 14
          點(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>
                  狠狠综合一区 | 久久久久性色Av免费毛片特级 | 91豆花视频在线 | 色视频网| 俺去俺来也在线www色情网 |