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

字典组件接口优化

背景

在很多的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对处理异步有着很多的优势!

相关推荐
恋猫de小郭1 分钟前
小米 HyperOS 4 大变样?核心应用以 Rust / Flutter 重写,不兼容老系统
android·前端·人工智能·flutter·ios
李火火的安全圈7 分钟前
基于Yakit、Wavely实现CVE-2025-55182(React Server Components(RSC)) 反序列化漏洞挖掘和POC编写
前端·react.js
ALex_zry14 分钟前
分布式缓存性能优化策略
分布式·缓存·性能优化
Dxy123931021616 分钟前
MySQL如何使用EXPLAIN分析SQL语句:从执行计划到性能优化
sql·mysql·性能优化
Orange_sparkle17 分钟前
dify的web页面如何传入user用户信息进行对话,而不是uuid
前端·人工智能
Amumu1213826 分钟前
Vue Router 和 常用组件库
前端·javascript·vue.js
霍理迪31 分钟前
CSS移动端开发及less使用方法
前端·css
2601_9498574331 分钟前
Flutter for OpenHarmony Web开发助手App实战:HTML参考
前端·flutter·html
爱内卷的学霸一枚34 分钟前
现代前端工程化实践:从Vue到React的架构演进与性能优化(7000字深度解析)
前端·vue.js·react.js
南风知我意95737 分钟前
【前端面试4】框架以及TS
前端·面试·职场和发展