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

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

背景简介

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

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

js 复制代码
/**
 * 数据缓存池
 * @param key 唯一标识
 * @param obj 被缓存的对象
 */
function CachedObj() {
  this.cacheMap = new Map(); //? 缓存池
  
  this.get = (key, obj?) => { //* 获取某一个promise的数据(第一次执行设置,第二次执行获取)
    if (!this.cacheMap.has(key) && obj) {
      this.set(key, obj)
    }
    return this.cacheMap.get(key);
  }
  this.set = (key, obj) => { //* 设置某一个promise的数据
    this.cacheMap.set(key, obj);
  }
  this.delete = (key) => { //* 删除某一个promise的数据
    this.cacheMap.delete(key)
  }
  this.clear = () => { //* 清空重置所有的数据
    this.cacheMap.clear()
  }
}
const cachedObjInstance = new CachedObj()

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

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

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

公共的地方设置异步缓存池的构造器以及公共的构造器实例

js 复制代码
/**
 * 异步缓存池
 * @param promise 被缓存的异步
 * @param key 唯一标识
 * @returns 同一个异步
 */
function CachedPromise() {
  this.cacheMap = new Map(); //? 缓存池
  
  this.get = (key, promiseFn?) => { //* 获取某一个promise的数据(第一次执行设置,第二次执行获取)
    if (!this.cacheMap.has(key) && promiseFn) {
      this.set(key, promiseFn())
    }
    return this.cacheMap.get(key);
  }
  this.set = (key, promise) => { //* 设置某一个promise的数据
    this.cacheMap.set(key, promise);
  }
  this.delete = (key) => { //* 删除某一个promise的数据
    this.cacheMap.delete(key)
  }
  this.clear = () => { //* 清空重置所有的数据
    this.cacheMap.clear()
  }
}
const cachedPromiseInstance = new CachedPromise()

业务内使用

js 复制代码
//todo 设置个性化待办的信息
const getWaitCustomizeInfo = async () => {
  if (AppModule.waitCustomizeInfo) { //* 单例模式,存在则不再请求接口
    return await AppModule.waitCustomizeInfo
  }
  const defaultCustomizeInfo = {
    waitPermission: 'personal', //? 默认"只看自己"
  }
  try {
    const res = await cachedPromise.get('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 CachedPromise(continueWhenFinished = false) {
  this.cacheMap = new Map(); //? 缓存池

  this.get = (key, promiseFn?) => { //* 获取某一个promise的数据(第一次执行设置,第二次执行获取)
    if (this.cacheMap.has(key)) { //* 已有缓存时
      // if (this.cacheMap.get(key).isFulfilled() && promiseFn) { //* 已有缓存,continueWhenFinished 为true,且缓存中的异步已经完成时,执行新的异步并缓存
      if (continueWhenFinished && typeof this.cacheMap.get(key).then !== 'function' && promiseFn) { //* 已有缓存,continueWhenFinished 为true,且缓存中的异步已经完成时,执行新的异步并缓存
        this.set(key, promiseFn())
      }
    }
    if (!this.cacheMap.has(key) && promiseFn) { //* 没有缓存数据时,进行设置
      this.set(key, promiseFn())
    }
    return this.cacheMap.get(key);
  }
  this.set = (key, promise) => { //* 设置某一个promise的数据
    this.cacheMap.set(key, promise);
  }
  this.delete = (key) => { //* 删除某一个promise的数据
    this.cacheMap.delete(key)
  }
  this.clear = () => { //* 清空重置所有的数据
    this.cacheMap.clear()
  }
}
const cachedPromiseInstance = new CachedPromise()```

注意实现

1、promise一旦新建就会立即执行,所以 要将promise保成函数传入;

2、构造器实例,必须在初始化调用接口的组件外部使用,才能起到缓存promise的作用;放在组件内,每次都会创建一个全新的缓存池

3、记得要处理promise rejected的场景

相关推荐
Y敲键盘的地方12 小时前
第9章 工具调用循环——Agent的行动闭环
java·服务器·前端
苏瞳儿12 小时前
vue3+pinia+mqtt实时响应连接
前端·javascript·vue.js
郝学胜-神的一滴12 小时前
系统设计 013:高并发系统缓存:从原理到实践全解析
java·开发语言·python·缓存·系统架构·php·软件构建
ayqy贾杰12 小时前
我同事,40了,他vibe coding了个App
前端·ios·客户端
深念Y12 小时前
DeepSeek/MiMo 推理链缓存代理:从内存到 SQLite 的两级缓存架构实战
数据库·缓存·架构·sqlite·内存·优化·分层
sichuanwww12 小时前
函数缓存lru_cache
缓存·函数缓存·lru_cache
暗冰ཏོ12 小时前
《2026 Vue2 + Vue3 完整学习指南:基础语法、路由缓存、登录拦截、项目实战与面试题》
前端·vue.js·vue·vue3·vue2
蜡台13 小时前
VUE 侧边按钮组,可自定义位置
前端·javascript·css
AI科技星13 小时前
维度原本——基于超复数谱系的全域维度统一理论
c语言·前端·javascript·网络·electron
遇事不決洛必達13 小时前
【爬虫随笔】常见加密算法特征总结
javascript·爬虫·逆向·加密算法