天天看點

前端緩存API請求資料的解決方案

前端緩存API請求資料的解決方案

1、背景

在一些項目中,有時候會出現不同子產品重複請求大量相同API接口的情況,特别是在一些功能相似的背景管理頁面中。

以下面這幾個頁面為例,每次進入頁面都需要請求等大量重複的下拉框資料,下拉框資料短時間内改動不大,但也不能在前端使用靜态資料,是以可以考慮在前端進行資料緩存,避免重複請求API。

前端緩存API請求資料的解決方案
前端緩存API請求資料的解決方案
前端緩存API請求資料的解決方案

2、 實作思路

主要有以下3個步驟:

  • 初次擷取資料,從伺服器中請求資料;
  • 建立一個映射表,将下拉框資料儲存起來,并同時記錄該資料的時間戳;
  • 後續再次請求時,首先從映射表中查找資料,如果可以查到資料且資料沒過期,則直接使用資料,否則重新從伺服器中擷取資料;

3、具體實作

3.1 、初次擷取資料

以下代碼中,首先調用 getLocalData 方法查找緩存,如果沒找到緩存,就向伺服器請求資料(this.$api.task.getCateListAll),擷取到資料後用 setLocalData 方法把資料緩存起來。

// 任務類型下拉框資料
// 首先判斷是否有緩存
if (!this.getLocalData('cate')) {
  /** 初次請求資料 */
  await this.$api.task.getCateListAll().then((res) => {
    this.m_taskPropOption.cate = this.$u.array.arrToSelect(res.data); // 使用資料
    this.m_taskPropDict.cate = this.$u.array.arrToObj(this.m_taskPropOption.cate, "id"); // 使用資料
    this.setLocalData('cate'); // 緩存資料
  });
}      

3.2 、建立映射表,緩存資料

緩存資料主要使用了浏覽器的API localStorage,如下面代碼中 setLocalData 方法,每次從伺服器擷取資料後,根據 key 将資料儲存在 localStorage 中,并且同時記錄時間戳,記錄時間戳是為了後面檢查緩存資料的過期時間:​

/** 設定緩存 - 建立映射表 */
setLocalData(key) {
  // 緩存資料
  localStorage.setItem(`task_${key}_option`, jsON.stringify(this.m_taskPropOption[key])); // 緩存資料
  localStorage.setItem(`task_${key}_dict`, jsON.stringify(this.m_taskPropDict[key])); // 緩存資料
  localStorage.setItem(`task_${key}_timestamp`, Date.now()); // 記錄時間戳
}      

3.3 、查找緩存資料

根據方法 getLocalData ,首先根據 key 從 localStorage 中查找緩存的時間戳(時間戳是在緩存資料時一起儲存的,如果有時間戳,則表示有緩存資料),如果有緩存時間并且判斷緩存時間未過期,則進一步從緩存中擷取資料給到程式使用:​

/** 擷取緩存 - 查找映射表 并 檢查過期時間 */
getLocalData(key) {
  let storageTimestamp = localStorage.getItem(`task_${key}_timestamp`);
  let expires = 1000 * 3600; // 有效時間
  let timestamp = Date.now();  // 目前時間戳
  // 從緩存中取資料(1h内資料)
  if (storageTimestamp && (timestamp - storageTimestamp) < expires) {
    let option = localStorage.getItem(`task_${key}_option`); // 從緩存中拿到資料給程式使用
    let dict = localStorage.getItem(`task_${key}_dict`); // 從緩存中拿到資料給程式使用
    this.m_taskPropOption[key] = JSON.parse(option);
    this.m_taskPropDict[key] = JSON.parse(dict);
    return true;
  }
  return false;
}      

3.4 、實作效果

使用緩存前進入頁面:

前端緩存API請求資料的解決方案

使用緩存後進入頁面:

前端緩存API請求資料的解決方案

由上圖可以看出,使用緩存前進入頁面需要請求7個api接口,而緩存了資料之後,進入頁面隻需要請求3個接口即可,确實起到了減少了請求接口數量的效果。

4、方案的不足之處及改善

本方案首要的不足在于前端無法準确獲知資料庫中資料的更新時間。目前暫時設定了緩存時間 expires = 3600 * 1000 ms,也就是說1h内資料被更新了的話,前端顯示的依然是緩存的舊資料,這一點暫時沒想到改善方法。

此外,緩存使用了 localStorage API。localStorage 的特點是隻要不手動清除,資料會一直儲存在浏覽器端,這樣使用者就沒有辦法清除緩存,要改善這一點的話可以換一個全局對象(vuex)來儲存資料,隻要頁面重新整理的話,緩存的資料會被清除。