减少重复的请求之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的场景

相关推荐
慧一居士27 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead28 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
Hellyc6 小时前
用户查询优惠券之缓存击穿
java·redis·缓存
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子7 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina7 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
coderlin_8 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js