通用组件-字典组件优化思路

字典组件接口优化

背景

在很多的PC端管理项目中,总会有很多字典的接口,对于重复字典接口,如果每一次都请求,会造成非必要的性能丢失。

思路

对于该痛点,我们能很快的想到复用接口请求的数据就好。而且一般像字典请求接口来说,请求参数简单固定化。对于这些接口,能实现map存储复用结果。

由于axios请求是个promise,只要第一次请求之后,将该promise存储起来,后续重复接口调用时都复用该接口。(promise的特性,状态一旦修改之后就不会被二次修改,永远都保持用一个值)

设计

javascript 复制代码
/**
 * 存放dict缓存的字段
 * 目前只针对页面级缓存,切换页面dictCacheMap会清空
 */
const dictCacheMap = new Map();
​
/**
 * 字典请求接口
 */
const dictUrl = [
  'dictDetail/list', // 获取字典,params: { dictName: String }
  'dictDetail/treeList', // 获取字典项树, parmas: { dictName: String }
];
​
/**
 * 判断是否命中缓存接口
 * @param {URL} url
 * @returns Boolean
 */
export const isDictUrl = url => {
  return dictUrl.some(dict => url.endsWith(dict));
};
​
/**
 * 判断是否已经缓存过字典
 * @param {String} dictName 请求的参数
 * @returns Boolean
 */
export const checkDictCache = dictName => {
  return dictCacheMap.has(dictName);
};
​
/**
 * 返回字典值
 * @param {String} dictName 请求的参数
 * @returns Promise
 */
export const getDictCache = dictName => {
  return dictCacheMap.get(dictName);
};
​
/**
 * 设置字典值
 * @param {String} dictName 请求的参数
 * @param {Promise} promise 请求promise
 * @returns Promise
 */
export const setDictCache = (dictName, promise) => {
  // 将请求的promise收集起来,重复的接口将该promise返回
  dictCacheMap.set(dictName, promise);
  return promise;
};
​
/**
 * 清除字典
 * @param  {...any} rest 清除的字典名,不输入默认清除全部
 */
export const clearDictCache = (...rest) => {
  if (rest.length === 0) {
    dictCacheMap.clear();
  } else {
    for (const v of rest) {
      dictCacheMap.delete(v);
    }
  }
};

在定义好数据存储的文件后,我们可对字典请求接口封装成组件,或是请求request拦截请求设置。在这里采用组件形式书写。

xml 复制代码
<!--
字典选择
-->
​
<template>
  <a-select     
    v-listening="$listening"
    v-bind="$attrs" 
    :value="dtValue" 
    :options="dictItems" 
 />
</template>
​
<script>
import {
  checkDictCache,
  getDictCache,
  setDictCache,
} from './dict-cache';
​
export default {
  props: {
    value: null, // 值
    dict: {
        type: String,
        default: ''
    }
  },
  data() {
    return {
      dtValue: this.value,
      dictItems: [], // 字典项
      url: {
        list: 'dict/list', // 平铺的字典项, params: { dictName: String }
      },
    };
  },
  computed: {
    // 请求配置
    requestOption() {
      const option = {
        method: 'post',
        params: {
          dictName: this.dict, // 请求的字典名
        },
      };
      return option;
    },
  },
  watch: {
    value(v) {
      this.dtValue = v;
    },
    // 请求配置变化后,触发一次接口调用
    requestOption() {
      this.fetchList();
    },
  },
  mounted() {
    this.fetchList();
  },
  methods: {
    fetchList() {
      // 是否命中字典缓存接口
      const fetchPromise = checkDictCache(this.dict)
        // 如果已经存在请求,复用之前请求的结果
        ? getDictCache(this.dict)
        // 如果不存在该请求,发送请求,并将请求promise复用起来
        : setDictCache(this.dict, this.fetchPromise());
      fetchPromise.then(res => {
        this.dictItems = res;
      });
    },
    // 发送请求
    fetchPromise() {
      return this.$$http(this.requestOption)
          .then(data => { 
            return data;
           });
    },
  },
};
</script>

对于字典请求接口缓存后,需要考虑删除缓存结果,一般来说我们针对页面级的缓存,当这个页面一直存在时,缓存就不会被清除。因此,清除缓存可以在路由的beforeEach钩子函数执行时主动清除缓存

javascript 复制代码
import { clearDictCache } from './dict-cache.js'
const router = createRouter({ ... })
​
router.beforeEach((to, from) => {
  clearDictCache()
  //
})

总结

接口缓存一种很常见的问题,很多方式都是采用map存储请求回来的 结果。但是在这种方式下会导致第一次数据还没请求到,到后续请求又需要该结果。因此,最好使用promise来兜底。promise对处理异步有着很多的优势!

相关推荐
一只蝉nahc17 分钟前
vue使用iframe内嵌unity模型,并且向模型传递信息,接受信息
前端·vue.js·unity
子兮曰1 小时前
Bun v1.3.12 深度解析:新特性、性能优化与实战指南
前端·typescript·bun
2401_885885041 小时前
易语言彩信接口怎么调用?E语言Post实现多媒体数据批量下发
前端
a1117762 小时前
Three.js 的前端 WebGL 页面合集(日本 开源项目)
前端·javascript·webgl
Kk.08022 小时前
项目《基于Linux下的mybash命令解释器》(一)
前端·javascript·算法
小李子呢02113 小时前
前端八股---闭包和作用域链
前端
IT_陈寒3 小时前
Redis的内存溢出坑把我整懵了,分享这个血泪教训
前端·人工智能·后端
m0_738120723 小时前
渗透测试基础ctfshow——Web应用安全与防护(五)
前端·网络·数据库·windows·python·sql·安全
Z_Wonderful3 小时前
基于 Vite 的 React+Vue 混部完整模板(含目录结构、依赖清单、启动脚本)
前端·vue.js·react.js
Rooting++4 小时前
腾讯无界微前端源码分析
前端