一、靈感來源
最近在做新需求開發的時候,我發現某些頁面進入時需要加載4、5個接口,我檢查這些接口,發現大部分是基礎資料,比如省、市、區或者某些特定分類(比如商品分類)等。這個資料需要通過後端接口請求擷取,然後将資料回顯到前端頁面,讓使用者找到自己想要查詢的篩選項。
每次進入帶有省份篩選條件的清單頁面,為了支援使用者可以按照某個省份進行篩選的操作,都會将省份接口請求一次,拿到全部的省份清單。其實省份資料更新的頻率很低,于是我就想如果用資料緩存替代接口請求是不是也可以?
二、假設與求證
再開始設計功能之前,我找到後端的同僚進行了确認,我們的省市區(周一問一下)除非有特殊情況,基本不會更新。于是為了保險,我将緩存設定為了會話緩存,沒有設定持久緩存。其實持久緩存設定過期時間也可以,但是因為是功能優化,優化的前提是不能帶來額外的問題,是以為了穩妥,我采用了會話緩存。
三、紙上得來終覺淺,絕知此事要躬行
“大抵學問隻有兩途,緻知力行而已。”我是個行動派,腦子裡有了這個想法就着手去實作。
我們的項目是用React架構實作的,是以下面的功能實作均用JSX文法。
3.1 功能流程圖
- provinceList:全部省份數組變量;
- 通過判斷sessionStorage中是否有provinceList的值确定是否還需要請求省份接口,如果有值,不請求接口,直接将sessionStorage中provinceList的值指派給provinceList變量;如果沒有值,請求接口,将接口傳回的provinceList值指派給provinceList變量,同時存到sessionStorage中。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAnYldHL0FWby9mZvwFN4ETMfdHLkVGepZ2XtxSZ6l2clJ3LcV2Zh1Wa9M3clN2byBXLzN3btgHL9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iN4YTN1YTOkNmY1UDZxETNzYzX5ATNwgTMwIzLcBTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
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都會去緩存中的資料,除非手動删除緩存或者關閉會話。