当前位置: 首页 > news >正文

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

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

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

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

/*** 数据缓存池* @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

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

/*** 异步缓存池* @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()

业务内使用

//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.dataconst savedInfo = personalMenus.menuPersonalValue ? JSON.parse(personalMenus.menuPersonalValue).headerValue : defaultCustomizeInfoconst waitCustomizeInfo = { id: personalMenus.id, ...savedInfo }AppModule.setWaitCustomizeInfo(waitCustomizeInfo)return waitCustomizeInfo}AppModule.setWaitCustomizeInfo(defaultCustomizeInfo)return defaultCustomizeInfo;} catch (error) {AppModule.setWaitCustomizeInfo(defaultCustomizeInfo)return defaultCustomizeInfo;}
}

完美解决!!!

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

/*** 异步缓存池* @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的场景

相关文章:

  • STM32F745IE 能进定时器中断,无法进主循环
  • ICM20948 DMP代码详解(48)
  • 【Flume Kafaka实战】Using Kafka with Flume
  • 4. 数据结构: 对象和数组
  • 如何使用GLib的单向链表GSList
  • UE学习篇ContentExample解读------Blueprint_Communication-下
  • ELK-05-skywalking监控SpringCloud服务日志
  • Qt/C++如何选择使用哪一种地图内核/不同地图的优缺点/百度高德腾讯地图/天地图/谷歌地图
  • AI运用在营销领域的经典案例及解析
  • 单片机长短按简单实现
  • Unity 与虚幻引擎对比:两大游戏开发引擎的优劣分析
  • 宝塔搭建nextcould 30docker搭建onlyoffic8.0
  • blue-crab
  • VS Code 配置 Anaconda Python 环境
  • 观察者模式(发布-订阅模式)
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • C++类的相互关联
  • Effective Java 笔记(一)
  • ERLANG 网工修炼笔记 ---- UDP
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JavaScript学习总结——原型
  • java中具有继承关系的类及其对象初始化顺序
  • leetcode386. Lexicographical Numbers
  • mockjs让前端开发独立于后端
  • Nodejs和JavaWeb协助开发
  • pdf文件如何在线转换为jpg图片
  • Redis 懒删除(lazy free)简史
  • webpack+react项目初体验——记录我的webpack环境配置
  • 从输入URL到页面加载发生了什么
  • 技术发展面试
  • 力扣(LeetCode)965
  • 前端路由实现-history
  • 使用Gradle第一次构建Java程序
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #includecmath
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (C语言)球球大作战
  • (WSI分类)WSI分类文献小综述 2024
  • (二)hibernate配置管理
  • (一)u-boot-nand.bin的下载
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • ******之网络***——物理***
  • .CSS-hover 的解释
  • .form文件_一篇文章学会文件上传
  • .net wcf memory gates checking failed
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .net6使用Sejil可视化日志
  • .NET开发人员必知的八个网站
  • .NET开源、简单、实用的数据库文档生成工具
  • //usr/lib/libgdal.so.20:对‘sqlite3_column_table_name’未定义的引用
  • [2024] 十大免费电脑数据恢复软件——轻松恢复电脑上已删除文件
  • [acm算法学习] 后缀数组SA