趣学前端 | 接口请求数据的缓存实践

举报
叶一一 发表于 2023/02/09 15:27:21 2023/02/09
【摘要】 前端开发中,如果通过后端接口请求获取的数据更新频率较低,但是使用率很高,可以考虑进行数据缓存减少请求。

一、灵感来源

最近在做新需求开发的时候,我发现某些页面进入时需要加载4、5个接口,我检查这些接口,发现大部分是基础数据,比如省、市、区或者某些特定分类(比如商品分类)等。这个数据需要通过后端接口请求获取,然后将数据回显到前端页面,让用户找到自己想要查询的筛选项。

每次进入带有省份筛选条件的列表页面,为了支持用户可以按照某个省份进行筛选的操作,都会将省份接口请求一次,拿到全部的省份列表。其实省份数据更新的频率很低,于是我就想如果用数据缓存替代接口请求是不是也可以?

二、假设与求证

再开始设计功能之前,我找到后端的同事进行了确认,我们的省市区(周一问一下)除非有特殊情况,基本不会更新。于是为了保险,我将缓存设置为了会话缓存,没有设置持久缓存。其实持久缓存设置过期时间也可以,但是因为是功能优化,优化的前提是不能带来额外的问题,所以为了稳妥,我采用了会话缓存。

三、纸上得来终觉浅,绝知此事要躬行

“大抵学问只有两途,致知力行而已。”我是个行动派,脑子里有了这个想法就着手去实现。

我们的项目是用React框架实现的,所以下面的功能实现均用JSX语法。

3.1 功能流程图

  • provinceList:全部省份数组变量;
  • 通过判断sessionStorage中是否有provinceList的值确定是否还需要请求省份接口,如果有值,不请求接口,直接将sessionStorage中provinceList的值赋值给provinceList变量;如果没有值,请求接口,将接口返回的provinceList值赋值给provinceList变量,同时存到sessionStorage中

image


3.2 UI交互

image

3.3 功能实现

  • 将该功能提炼成公共方法,根据需要获取的值的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;

设置省份数组对象

/** @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接口只请求了一次

image

浏览器缓存中sessionInfo对象已经有了数据,整个会话过程中,provinceList都会去缓存中的数据,除非手动删除缓存或者关闭会话。

image

四、总结

新的一年,我致力于性能优化,前端性能优化涉及到很多方面,其中一条为减少http/https请求,优化接口请求,也可以帮忙做到这一点。

最后,还是要提醒一点,优化尽量不要带来额外的问题,所以进行接口数据缓存的时候,需要考虑数据的更新频率,尽量选择更新频率低甚至不更新的数据进行优化操作,且如果做永久缓存的话,尽量设置缓存时效,避免带来因为数据缓存导致数据不准的问题。

作者:非职业「传道授业解惑」的开发者叶一一
简介:「趣学前端」、「CSS畅想」系列作者,华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。