前端基礎向~封裝Axios優化頁面Loading效果

語言: CN / TW / HK

highlight: an-old-hope theme: hydrogen


持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第N天,點選檢視活動詳情

前言

最近老是做後臺專案,很多頁面需要同時請求多個數據,並且為了統一 loading 樣式和載入效果、避免多個請求發起和結束之間有細微間隔導致 loading 閃爍的情況,所以就改造了一下 Axios 的封裝,在攔截器中增加全屏 Loading 的處理。

1. 目標效果

根據目前的專案需求,總結了以下場景和對應要求:

  • 在請求時開啟 Loading 效果,請求結束時關閉;

  • 如果有多個請求,則儘量保證多個請求間隔不會存在閃爍,也不會新增多個 Loading 效果;

  • 可以配置是否開啟全屏 Loading

第一眼看到這個需求,就想到的肯定有防抖,用來實現一個時延效果,避免首次載入時可能出現的閃爍;但是在第一次請求開啟 Loading 之後如何保證在關閉時就是最晚結束的請求呢?

這裡我採用的方案就是通過一個數組長度來控制。

2. 方案實現

首先,是編寫一個 request.js 檔案,引入 Axios 和 ElementUI 的 Loading 元件,並初始化一個數組和 loading 元件例項。

```javascript import axios from "axios"; import { Loading } from "element-ui";

let loadingInstance; const LoadingOpts = { text: "載入中,請稍後......" };

const RequestStack = []; let RequestId = 0; // 也可以不用 ```

這裡我定義了一個自增式的ID,用來標識當前的請求,也可以取消,對實際邏輯沒有影響。

然後,我們再通過 lodash 提供的 debounce 防抖函式,封裝一個 Loading 的關閉方法。

```javascript import { debounce } from "lodash";

const closeLoading = debounce(() => { if (!RequestStack.length) { loadingInstance && loadingInstance.close(); loadingInstance = null } }, 100); ```

只有當此時的請求陣列的長度為 0 的時候,才關閉 Loading 效果。

因為在 Node 的模組環境下,一個 js 檔案就相當於一個模組,只要沒有匯出,內部的變數就是相對安全的;所以 RequestStack 的操作和長度基本不會被外界改變,可以確保該陣列長度就是請求中的 http 請求個數;當長度為 0 時,那肯定就是沒有 http 請求,需要關閉 Loading 了。

而增加防抖操作,也是為了避免有些同步請求的操作導致的閃爍。

最後,就是增加 axios 的攔截器配置,在發起時向陣列中插入一個元素,在結束時(異常、正常等)刪除一個元素,並呼叫 closeLoading 關閉載入效果。

```javascript // 新增請求攔截器 axios.interceptors.request.use(function (config) { // 開啟 Loading if (config.fullscreen) { !loadingInstance && (loadingInstance = Loading.service(LoadingOpts)) RequestStack.push(RequestId++); } return config; }, function (error) { // 發生錯誤時清除一個元素 RequestStack.pop(); closeLoading(); return Promise.reject(error); });

// 新增響應攔截器,不管成功還是失敗都需要關閉 loading axios.interceptors.response.use(function (response) { RequestStack.pop(); closeLoading(); return response; }, function (error) { RequestStack.pop(); closeLoading(); return Promise.reject(error); }); ```

3. 總結

總的來說,這個方案原理很簡單:通過閉包來實現多個請求時數量的統一和 CloseLoading 的正確時機。但是也有一些問題,比如有些大資料請消耗大量時間,或者請求間隔大於100ms,一樣有可能影響使用者體驗,實際的載入動畫效果依然要根據專案情況來進行調整。

最後一句話,閉包真好用~~~