天天看點

「工作小記」接口請求資料的緩存實踐

一、靈感來源

最近在做新需求開發的時候,我發現某些頁面進入時需要加載4、5個接口,我檢查這些接口,發現大部分是基礎資料,比如省、市、區或者某些特定分類(比如商品分類)等。這個資料需要通過後端接口請求擷取,然後将資料回顯到前端頁面,讓使用者找到自己想要查詢的篩選項。

每次進入帶有省份篩選條件的清單頁面,為了支援使用者可以按照某個省份進行篩選的操作,都會将省份接口請求一次,拿到全部的省份清單。其實省份資料更新的頻率很低,于是我就想如果用資料緩存替代接口請求是不是也可以?

二、假設與求證

再開始設計功能之前,我找到後端的同僚進行了确認,我們的省市區(周一問一下)除非有特殊情況,基本不會更新。于是為了保險,我将緩存設定為了會話緩存,沒有設定持久緩存。其實持久緩存設定過期時間也可以,但是因為是功能優化,優化的前提是不能帶來額外的問題,是以為了穩妥,我采用了會話緩存。

三、紙上得來終覺淺,絕知此事要躬行

“大抵學問隻有兩途,緻知力行而已。”我是個行動派,腦子裡有了這個想法就着手去實作。

我們的項目是用React架構實作的,是以下面的功能實作均用JSX文法。

3.1 功能流程圖

  • provinceList:全部省份數組變量;
  • 通過判斷sessionStorage中是否有provinceList的值确定是否還需要請求省份接口,如果有值,不請求接口,直接将sessionStorage中provinceList的值指派給provinceList變量;如果沒有值,請求接口,将接口傳回的provinceList值指派給provinceList變量,同時存到sessionStorage中。
「工作小記」接口請求資料的緩存實踐

3.2 UI互動

「工作小記」接口請求資料的緩存實踐

3.3 功能實作

3.3.1 公共方法

  • 将該功能提煉成公共方法,根據需要擷取的值的type不同區分數組對象和api接口請求;
  • apiMethodObj:定義接口方法變量,包括api接口和api接口入參兩個變量。用定義對象變量的方式替代條件判斷的方式,更友善維護和擴充,且不會帶來額外的測試工作量;
  • callback: 回調函數,将最終擷取的資料通過回調傳回;
/**
 * @description 公共方法-擷取sessionStorage資料
 * @param {string} type 搜尋項數組對象type值
 * @param {Function} callback 回調函數
 * @return {Array} 搜尋項數組對象
 */
import { findProvince } from '@/api/base';

const getSessionInfo = (type, callback) => {
  let sessionInfo = JSON.parse(sessionStorage.getItem('sessionInfo')) || {};
  let list = sessionInfo[type] ? sessionInfo[type] : [];
  // =>true: sessionStorage的數組對象值為空時,請求接口
  if (list.length === 0) {
    /** @name 接口方法變量 */
    let apiMethodObj = {
      provinceList: {
        api: findProvince, // api接口
        params: {
          size: 100,
          page: 1,
        }, // api接口入參
      },
    };
    /** @name 接口方法item變量 */
    let apiItem = apiMethodObj[type];
    apiItem['api'](apiItem['params']).then(res => {
      if (res) {
        // 重置sessionStorage中的sessionInfo值
        sessionInfo[type] = list;
        sessionStorage.setItem('sessionInfo', JSON.stringify(sessionInfo));
        // 回調數組對象
        callback && callback(res.list);
      }
    });
  } else {
    // 回調數組對象
    callback && callback(list);
  }
};

export default getSessionInfo;      

3.3.2 使用

  • 設定省份數組對象
/** @name 設定省份數組對象 */
const [provinceList, setProvinceList] = useState([]);      
  • 搜尋通過anti提供的form表單實作,搜尋項為select下拉
<Form labelAlign='left' onFinish={this.handleSearch} ref={this.formRef}>
  <Form.Item label='省份' name='provinceId'>
    <Select placeholder='請選擇' allowClear>
      {provinceList.map(item => (
        <Select.Option key={item.provinceId} value={item.provinceId}>
          {item.provinceName}
        </Select.Option>
      ))}
    </Select>
  </Form.Item>
</Form>;      
  • 擷取provinceList的值
useEffect(() => {
  getSessionInfo('provinceList', list => {
    setProvinceList(list);
  });
}, []);      

3.4 小結

以上省份清單資料緩存的功能就實作了。我們來看一下接口請求是否隻出現了一次。下面的截圖是我第一次進入頁面到不斷重新整理頁面的截圖,可以看到findProvince接口隻請求了一次

「工作小記」接口請求資料的緩存實踐

浏覽器緩存中sessionInfo對象已經有了資料,整個會話過程中,provinceList都會去緩存中的資料,除非手動删除緩存或者關閉會話。

「工作小記」接口請求資料的緩存實踐

四、總結

繼續閱讀