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

          幾行代碼,優(yōu)雅的避免接口重復請求!同事都說好!

          共 8441字,需瀏覽 17分鐘

           ·

          2024-08-01 09:15

          點擊上方 前端Q,關(guān)注公眾號

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

          背景簡介

          我們?nèi)粘i_發(fā)中,經(jīng)常會遇到點擊一個「按鈕」或者進行「搜索」時,請求接口的需求。

          如果我們不做優(yōu)化,連續(xù)點擊「按鈕」或者進行「搜索」,接口會重復請求。

          ?

          首先,這會導致性能浪費!最重要的,如果接口響應比較慢,此時,我們在做其他操作會有一系列bug!

          ?

          那么,我們該如何規(guī)避這種問題呢?

          如何避免接口重復請求

          防抖節(jié)流方式(不推薦)

          使用防抖節(jié)流方式避免重復操作是前端的老傳統(tǒng)了,不多介紹了

          防抖實現(xiàn)

          <template>
            <div>
              <button @click="debouncedFetchData">請求</button>
            </div>

          </template>
          <script setup>
          import { ref } from 'vue';
          import axios from 'axios';

          const timeoutId = ref(null);

          function debounce(fn, delay{
            return function(...args{
              if (timeoutId.value) clearTimeout(timeoutId.value);
              timeoutId.value = setTimeout(() => {
                fn(...args);
              }, delay);
            };
          }

          function fetchData({
            axios.get('http://api/gcshi)  // 使用示例API
              .then(response => {
                console.log(response.data);
              })
          }

          const debouncedFetchData = debounce(fetchData, 300);
          </script>

          「防抖(Debounce)」

          • 在setup函數(shù)中,定義了timeoutId用于存儲定時器ID。
          • debounce函數(shù)創(chuàng)建了一個閉包,清除之前的定時器并設(shè)置新的定時器,只有在延遲時間內(nèi)沒有新調(diào)用時才執(zhí)行fetchData。
          • debouncedFetchData是防抖后的函數(shù),在按鈕點擊時調(diào)用。

          節(jié)流實現(xiàn)

          <template>
            <div>
              <button @click="throttledFetchData">請求</button>
            </div>

          </template>
          <script setup>
          import { ref } from 'vue';
          import axios from 'axios';

          const lastCall = ref(0);

          function throttle(fn, delay{
            return function(...args{
              const now = new Date().getTime();
              if (now - lastCall.value < delay) return;
              lastCall.value = now;
              fn(...args);
            };
          }

          function fetchData({
            axios.get('http://api/gcshi')  //
              .then(response => {
                console.log(response.data);
              })
          }

          const throttledFetchData = throttle(fetchData, 1000);
          </script>

          「節(jié)流(Throttle)」

          • 在setup函數(shù)中,定義了lastCall用于存儲上次調(diào)用的時間戳。
          • throttle函數(shù)創(chuàng)建了一個閉包,檢查當前時間與上次調(diào)用時間的差值,只有大于設(shè)定的延遲時間時才執(zhí)行fetchData。
          • throttledFetchData是節(jié)流后的函數(shù),在按鈕點擊時調(diào)用。

          節(jié)流防抖這種方式感覺用在這里不是很絲滑,代碼成本也比較高,因此,很不推薦!

          請求鎖定(加laoding狀態(tài))

          請求鎖定非常好理解,設(shè)置一個laoding狀態(tài),如果第一個接口處于laoding中,那么,我們不執(zhí)行任何邏輯!

          <template>
            <div>
              <button @click="fetchData">請求</button>
            </div>

          </template>

          <script setup>
          import { ref } from 'vue';
          import axios from 'axios';

          const laoding = ref(false);

          function fetchData() {
            /
          / 接口請求中,直接返回,避免重復請求
            if(laoding.value) return
            laoding.value = true
            axios.get('http:/
          /api/gcshi')  //
              .then(response => {
                laoding.value = fasle
              })
          }

          const throttledFetchData = throttle(fetchData, 1000);
          </script>

          這種方式簡單粗暴,十分好用!

          「但是也有弊端,比如我搜索A后,接口請求中;但我此時突然想搜B,就不會生效了,因為請求A還沒響應」

          因此,請求鎖定這種方式無法取消原先的請求,只能等待一個請求執(zhí)行完才能繼續(xù)請求。

          axios.CancelToken取消重復請求

          基本用法

          axios其實內(nèi)置了一個取消重復請求的方法:axios.CancelToken,我們可以利用axios.CancelToken來取消重復的請求,爆好用!

          首先,我們要知道,aixos有一個config的配置項,取消請求就是在這里面配置的。

          <template>
            <div>
              <button @click="fetchData">請求</button>
            </div>

          </template>

          <script setup>
          import { ref } from 'vue';
          import axios from 'axios';

          let cancelTokenSource = null;


          function fetchData() {
            if (cancelTokenSource) {
              cancelTokenSource.cancel('取消上次請求');
              cancelTokenSource = null;
            }
            cancelTokenSource = axios.CancelToken.source();
            
            axios.get('http:/
          /api/gcshi',{cancelToken: cancelTokenSource.token})  //
              .then(response => {
                laoding.value = fasle
              })
          }

          </script>

          我們測試下,如下圖:可以看到,重復的請求會直接被終止掉!

          CancelToken官網(wǎng)示例

          ?

          官網(wǎng)使用方法傳送門:https://www.axios-http.cn/docs/cancellation

          ?
          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 {
              // 處理錯誤
            }
          });

          axios.post('/user/12345', {
            name'new name'
          }, {
            cancelToken: source.token
          })

          // 取消請求(message 參數(shù)是可選的)
          source.cancel('Operation canceled by the user.');

          也可以通過傳遞一個 executor 函數(shù)到 CancelToken 的構(gòu)造函數(shù)來創(chuàng)建一個 cancel token:

          const CancelToken = axios.CancelToken;
          let cancel;

          axios.get('/user/12345', {
            cancelTokennew CancelToken(function executor(c{
              // executor 函數(shù)接收一個 cancel 函數(shù)作為參數(shù)
              cancel = c;
            })
          });

          // 取消請求
          cancel();

          注意: 可以使用同一個 cancel token 或 signal 取消多個請求。

          在過渡期間,您可以使用這兩種取消 API,即使是針對同一個請求:

          const controller = new AbortController();

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

          axios.get('/user/12345', {
            cancelToken: source.token,
            signal: controller.signal
          }).catch(function (thrown{
            if (axios.isCancel(thrown)) {
              console.log('Request canceled', thrown.message);
            } else {
              // 處理錯誤
            }
          });

          axios.post('/user/12345', {
            name'new name'
          }, {
            cancelToken: source.token
          })

          // 取消請求 (message 參數(shù)是可選的)
          source.cancel('Operation canceled by the user.');
          // 或
          controller.abort(); // 不支持 message 參數(shù)

          往期推薦


          某一線前端小組長的 Code Review 分享
          小程序可測性能力建設(shè)與實踐
          JavaScript Set新增7個方法

          最后


          • 歡迎加我微信,拉你進技術(shù)群,長期交流學習...

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

          點個在看支持我吧

          瀏覽 63
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  成人在线亚洲色图 | 青草国产在线 | 国产黄色视频www | 男女内射视频 | 91av在线观看免费一区 |