项目场景:

在项目中,一个表格里可能会有一个数据属于字典类型,然后使用字典转义公共组件,如下:(dict-show文件在下方相关代码下)

为什么一个接口调用一次但后端的方法被调用两次java_es6

这样就会有一个问题,每条数据都需要调用一次字典接口,同一个接口多次调用,控制台如下:

注意:不同的dictType的多次调用是正常的,因为参数不一样,只能每次都调用;这里的多次调用只的是同样参数同样接口的多次调用

相关代码

dict-show.vue 字典文件:

<template>
  <div>
    <el-input v-if="isInput" :value="dictName" readonly :disabled="disabled"/>
    <span v-else>{{ dictName }}</span>
  </div>
</template>

<script>
import { getDictDataByDictType} from "@/api/common.js";
export default {
  name: "DictShow",
  components: {},
  props: {
    dictId: {
      type: String,
      default: ""
    },
    dictType: {
      type: String,
      required: false,
      default: ""
    },
    isInput: {
      type: Boolean,
      default: false,
    },
    disabled:{
      type: Boolean,
      default: false,
    }
  },
  data() {
    return {
      dictName: "",
      dictArr:[],
      dictNameArr: []
    };
  },
  watch: {
    dictId(val) {
      if (val) {
        this.getDictArr();
      } else {
        this.dictName = ""
      }
    },
  },
  mounted() {
    if (this.dictId) {
      this.getDictArr();
    } else {
      this.dictName = ""
    }
  },
  methods: {
  	//根据dictId在字典列表中找到对应文字(可多个)
    getDictName() {
      this.dictNameArr = []
      const arr = this.dictId.split(",");
      for (let i = 0; i < arr.length; i++) {
        let tem = this.dictArr.filter(item=>{
          return item.dictValue === arr[i]
        })
        tem = tem && tem.length > 0 ? tem[0].dictLabel : "";
        this.dictNameArr.push(tem)
      }
      if (this.dictNameArr.length === 1) {
        this.dictName = this.dictNameArr[0]
      } else {
        let str = ''
        for (let i = 0; i < this.dictNameArr.length; i++) {
          str += this.dictNameArr[i] + ','
        }
        this.dictName = str.slice(0,-1)
      }
    },
    //获取字典列表
    getDictArr () {
      getDictDataByDictType(this.dictType).then(res => {
        this.dictArr = res.data
        if (this.dictArr.length > 0) {
          this.getDictName();
        }
      })
      .catch((err) => {});
    }
  },
};
</script>

api/common.js文件:

import axios from 'axios'

export const getDictDataByDictType = (dictType) => {
    return axios.request({
      url: "/getDictDataListByDictType",
      params: {
        dictType: dictType
      }
    })
}

解决方案:添加remote.js文件,并在接口封装时使用:

解决后的api/common.js文件,多封装一层:

import { remoteRequest } from '@/utils/remote.js'
import axios from 'axios'

export const getDictDataByDictType = (dictType) => {
  return remoteRequest('getDictDataByDictType', dictType, () => {
    return axios.request({
      url: "/getDictDataListByDictType",
      params: {
        dictType: dictType
      }
    })
  })
}

utils/remote.js文件(可直接拿去用):

const cache = new Map()

const cacheTime = new Map()
/**
 * 远程获取[避免重复请求]
 * @param prefix 前缀
 * @param params 参数配置
 * @param remoteFunc 反馈参数
 * @param repeatRequest 是否重复请求
 * @returns {Promise<any>|Promise<T | never>}
 */
export function remoteRequest(prefix, params, remoteFunc, repeatRequest = true, requestTime = 10000) {
  if (params == null) {
    return new Promise((resolve) => {
      resolve([])
    })
  }

  const timeKey = prefix + '#' + JSON.stringify(params)
  let time = ''
  if (repeatRequest) {
    const curTime = new Date().getTime()
    time = cacheTime.get(timeKey)
    if (time == null) {
      cacheTime.set(timeKey, curTime)
      time = curTime
    }

    if (curTime - requestTime >= time) { // 2秒内的请求都重新请求
      // 清除缓存换个请求
      cacheTime.clear()
      cacheTime.set(timeKey, curTime)
      time = curTime
    }
  }

  const key = timeKey + '#' + time

  // 远程获取
  let item = cache.get(key)
  if (item == null || item.error === true) {
    // 还没加载过
    if (item == null) {
      item = { loading: true, callbacks: [] }
      cache.set(key, item)
    }

    item.loading = true
    item.error = false

    // 远程加载
    return remoteFunc().then((data) => {
      // prop mapping
      item.data = data
      // 之前注册过的callback全部触发
      for (const callback of item.callbacks) {
        callback(item.data)
      }
      item.loading = false
      item.callbacks = []
      return data
    }).catch(() => {
      item.loading = false
      item.error = true
    })
  } else if (item.loading === true) {
    // 正在加载中,注册callback,等加载完了之后,再统一触发,就只需要向服务器请求一次数据模版
    return new Promise((resolve) => {
      const callback = (data) => {
        resolve(data)
      }
      item.callbacks.push(callback)
    })
  } else {
    //  从缓存拿
    return new Promise((resolve) => {
      resolve(item.data)
    })
  }
}
const cacheTrans = new Map()
const cacheTransTime = new Map()
/**
 * 远程获取数据合并同一请求 [避免重复请求]
 * @param prefix 前缀
 * @param id 参数配置
 * @returns {Promise<any>|Promise<T | never>}
 */
export function remoteTransRequest(prefix, id) {
  // 当id变化了(不一致)时,仍然认为是同意请求,不合理
  // prefix作为Map的key,应具有唯一性,所以加上参数,使其唯一性加强
  if (Object.prototype.toString.call(id) === '[object Object]') {
    prefix = prefix + '#' + JSON.stringify(id)
  } else {
    prefix = prefix + '#' + id
  }
  const curTime = new Date().getTime()
  const timeOut = 2000

  let time = cacheTransTime.get(prefix)
  if (time == null) {
    cacheTransTime.set(prefix, curTime)
    time = curTime
  }
  if (curTime - timeOut >= time) { // 2秒内的请求都重新请求
    // 清除缓存换个请求
    cacheTransTime.clear()
    cacheTransTime.set(prefix, curTime)
    time = curTime
  }

  const key = prefix + '#' + time
  // 汇总接口
  let item = cacheTrans.get(key)

  let idVal = id
  if (Object.prototype.toString.call(id) === '[object Object]') {
    idVal = JSON.stringify(id)
  }
  if (item == null || item.error === true) {
    // 还没加载过
    if (item == null) {
      item = { loading: true, ids: new Set(), callbacks: [] }
      cacheTrans.set(key, item)
    }
    item.loading = true
    item.ids = item.ids.add(idVal)

    const remoteFunc = (ids) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(ids)
        }, 100)
      })
    }
    return remoteFunc(item.ids).then((ids) => {
      item.ids = ids
      // 之前注册过的callback全部触发
      for (const callback of item.callbacks) {
        callback(ids)
      }
      item.loading = false
      item.callbacks = []
      return ids
    })
  } else if (item.loading === true) {
    // 正在加载中,注册callback,等加载完了之后,再统一触发,就只需要向服务器请求一次数据模版
    return new Promise((resolve) => {
      const callback = (ids) => {
        item.ids = ids.add(idVal)
        resolve(item.ids)
      }
      item.callbacks.push(callback)
    })
  } else {
    //  从缓存拿
    return new Promise((resolve) => {
      resolve(item.ids)
    })
  }
}

总结

之后再打开控制台,就都只有一次啦!

为什么一个接口调用一次但后端的方法被调用两次java_js_02

写博客是为了记笔记!