减少重复的请求之promise缓存池(闭包版) —— 缓存promise,多次promise等待并返回第一个promise的结果

减少重复的请求之promise缓存池 ------ 缓存promise,多次promise等待并返回第一个promise的结果

背景简介

当一个业务组件初始化调用了接口,统一个页面多吃使用同一个组件,将会请求大量重复的接口

如果将promise当作一个普通的对象,进行缓存

js 复制代码
function cacheObj() {
  const cacheMap = new Map(); //? 缓存池
  return (key, obj?) => {
    if (!cacheMap.has(key) && obj) { //* 没有缓存数据时,进行设置
      cacheMap.set(key, obj)
    }
    return cacheMap.get(key)
  }
}
const cacheObjCommon = cacheObj()

此时会发现,依旧会多次执行相同的promise(调用多个相同的接口),所以

promise的缓存,难点是如何将一旦新建就会立即执行的promise缓存

那如何让promise步立即执行,我想到了函数,第一个设置并缓存promise时,执行promise

公共的地方设置异步缓存池的闭包

js 复制代码
/**
 * 异步缓存池 ------ 闭包版本
 * @param key 唯一标识
 * @param promise 被缓存的异步
 * @param promiseFn 返回需要缓存异步的函数
 */
function cachePromise(continueWhenFinished = false) {
  const cacheMap = new Map(); //? 缓存池
  return (key, promiseFn?) => {
    if (!cacheMap.has(key) && promiseFn) { //* 没有缓存数据时,进行设置
      cacheMap.set(key, promiseFn())
    }
    return cacheMap.get(key)
  }
}
const cachePromiseCommon = cachePromise()```

业务内使用
```js
import { cachePromiseCommon as cachePromise } from '@/components/BaseSearchTable/utils';

const getWaitCustomizeInfo = async () => {
  if (AppModule.waitCustomizeInfo) { //* 单例模式,存在则不再请求接口
    return AppModule.waitCustomizeInfo
  }
  const defaultCustomizeInfo = {
    waitPermission: 'personal', //? 默认"只看自己"
  }
  try {
    const res = await cachePromise('globalWaitCustomizeInfo', () => system.userMenuPersonal.userMenuPersonalDetail.request({ menuCode: 'globalWaitCustomizeInfo' }))
    if (res.data) {
      const personalMenus = res.data
      const savedInfo = personalMenus.menuPersonalValue ? JSON.parse(personalMenus.menuPersonalValue).headerValue : defaultCustomizeInfo
      const waitCustomizeInfo = { id: personalMenus.id, ...savedInfo }
      AppModule.setWaitCustomizeInfo(waitCustomizeInfo)
      return waitCustomizeInfo
    }
    AppModule.setWaitCustomizeInfo(defaultCustomizeInfo)
    return defaultCustomizeInfo;
  } catch (error) {
    AppModule.setWaitCustomizeInfo(defaultCustomizeInfo)
    return defaultCustomizeInfo;
  }
}

完美解决!!!

当缓存中的异步完成后,还继续执行下一个异步时,可以改造一下,使用isFulfilled或者then来判断,异步是否完成

js 复制代码
/**
 * 异步缓存池 ------ 闭包版本
 * @param continueWhenFinished 当缓存中的异步完成后,继续执行下一个异步
 * @param key 唯一标识
 * @param promise 被缓存的异步
 * @param promiseFn 返回需要缓存异步的函数
 */
function cachePromise(continueWhenFinished = false) {
  const cacheMap = new Map(); //? 缓存池
  return (key, promiseFn?) => {
    if (cacheMap.has(key)) { //* 已有缓存时
      // if (this.cacheMap.get(key).isFulfilled() && promiseFn) { //* 已有缓存,continueWhenFinished 为true,且缓存中的异步已经完成时,执行新的异步并缓存
      if (continueWhenFinished && typeof cacheMap.get(key).then !== 'function' && promiseFn) { //* 已有缓存,continueWhenFinished 为true,且缓存中的异步已经完成时,执行新的异步并缓存
        cacheMap.set(key, promiseFn())
      }
    }
    if (!cacheMap.has(key) && promiseFn) { //* 没有缓存数据时,进行设置
      cacheMap.set(key, promiseFn())
    }
    return cacheMap.get(key)
  }
}
const cachePromiseCommon = cachePromise()
复制代码
> 注意实现
1、promise一旦新建就会立即执行,所以 要将promise保成函数传入;
2、构造器实例,必须在初始化调用接口的组件外部使用,才能起到缓存promise的作用;放在组件内,每次都会创建一个全新的缓存池
3、记得要处理promise rejected的场景
相关推荐
宿6747 小时前
vue3-config
前端·javascript·vue.js
ShineWinsu10 小时前
对于 Vue 3:从为什么学 Vue,到声明式渲染与数据响应式的解析
前端·javascript·vue.js
leoZ23111 小时前
第 6 篇:SchemaForm 渲染器核心实现
前端·javascript·vue.js·人工智能·神经网络·机器学习·自然语言处理
CoderYanger11 小时前
前端基础——JavaScript(基础语法)(下篇)
java·开发语言·前端·javascript·程序人生·面试·职场和发展
还是大剑师兰特12 小时前
vue项目浏览器版本判别,低于IE11跳转到新页面
前端·javascript·vue.js
想吃火锅100512 小时前
【leetcode】42.接雨水js
开发语言·javascript·ecmascript
雪芽蓝域zzs13 小时前
第十六节:递归组件实现无限层级折叠侧边栏菜单
开发语言·javascript·ecmascript
BillKu14 小时前
vue3 字符串排序 localeCompare,确保排序为 “B01“, “B10“, “B2“
前端·javascript·vue.js
然我15 小时前
从 Service 到生命周期:Agent Runtime 的插件内核
前端·javascript·agent
用户69190268133915 小时前
Agent 记忆处理机制详解:从变量数据类型到内存模型
javascript·架构