Promise缓存
Posted 秋天1014童话
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise缓存相关的知识,希望对你有一定的参考价值。
背景:
经过业务长时间打磨,往往会沉淀诸多公用的方法和能力,比如获取用户信息,获取某场景配置信息等。在我们进行可视化搭建页面时,往往会存在多模块调用同一个公用方法的情况,比如这个模块需要进行用户信息展示,那个模块需要判断用户是否符合活动人群。如果全局没做状态管理的话,每调用一次,就会发起一次请求。在大流量的场景下,不但会提升qps,可能触发服务器调用阀值,影响用户体验,同时也很浪费服务器资源,这个时候我们就可以去做一个Promise的缓存。这也是面试经常被多形式问到的问题。
一个普通的异步调用
let times = 1; const mockRequest = ()=> return new Promise((resolve, reject)=> setTimeout(()=> console.log('执行第'+times+'次'); let userId = '123'; times++; resolve(userId); , 3000) ) const doMoreRequest = () => //执行多次 mockRequest().then(res=> console.log('res1:', res) ) mockRequest().then(res=> console.log('res2:', res) )
结果:
执行第1次 res1: 123 执行第2次 res2: 123
promise缓存的模拟简化代码:
获取了用户信息之后将promise结果记录在缓存中。因为用户信息在h5活动场景下一般固定(换绑账号等情况除外),此处使用对象值存储。如果有多个key/value值,可以使用map。
let times = 1; let promiseCache = null; // 此处值固定,如果有个key/value值,可以使用map const mockRequest = ()=> return new Promise((resolve, reject)=> setTimeout(()=> console.log('执行第'+times+'次'); let userId = '123'; times++; resolve(userId); , 3000) ) const mockRequestMemoize = ()=> if (!promiseCache) const userPromise = mockRequest(); promiseCache = userPromise; // 获取了用户信息之后将promise结果记录在缓存中 return promiseCache; const doMoreRequestMemoize = () => //模拟执行多次 mockRequestMemoize().then(res=> console.log('res1:', res) ) mockRequestMemoize().then(res=> console.log('res2:', res) ) setTimeout(()=> mockRequestMemoize().then(res=> console.log('res3:', res) ) , 2000) doMoreRequestMemoize();
结果:
结果: 执行第1次 res1: 123 res2: 123 res3: 123
为什么是缓存promise,而不是缓存结果?
如果是缓存结果,那么需要第一个调用拿到请求结果后,才会记录缓存,但当此时,再来第二个请求,将会再次发起请求。
无论时间如何,当我们对进行多次调用时,只会触发一个网络请求。这是因为所有后续调用者都收到与第一个相同的 Promise 单例。
错误处理
除了正常接口返回,还应考虑接口失败的可能性。如果已缓存了被拒绝的 Promise ,则所有将来的调用都将以同样的失败 Promise 被拒绝。
let times = 1; let promiseCache = null; const mockRequest = ()=> return new Promise((resolve, reject)=> setTimeout(()=> console.log('执行第'+times+'次'); let userId = '123'; times++; reject(userId); // 此处拒绝返回 ,3000) ) const mockRequestMemoize = ()=> if (!promiseCache) const userPromise = mockRequest(); promiseCache = userPromise; return promiseCache; const doMoreRequestMemoize = () => //模拟执行多次 mockRequestMemoize().then(res=> console.log('res1:', res) ).catch(err=> console.log('err1:', err) ) mockRequestMemoize().then(res=> console.log('res2:', res) ).catch(err=> console.log('err2:', err) ) setTimeout(()=> mockRequestMemoize().then(res=> console.log('res3:', res) ).catch(err=> console.log('err3:', err) ) , 2000) doMoreRequestMemoize();
结果:
执行第1次 err1: 123 err2: 123 err3: 123
##
参考
- Promise缓存:高级 Promise 模式 - Promise缓存 - 云+社区 - 腾讯云
- 扩展lodash的momerize:lodash源码中的memoize函数_Story..的博客-CSDN博客
以上是关于Promise缓存的主要内容,如果未能解决你的问题,请参考以下文章
在expressJS中如何创建一个缓存,使多个请求等待相同的promise [重复]