-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
前端 api 请求缓存方案 #2
Comments
大佬的文章写得很不错啊,可以授权给公众号 全栈修炼 转载吗?会注明作者及来源的,谢谢。 |
@biaochenxuying 可以的 |
promise的方案例子有问题吧 |
方案三中代码部分有问题 |
proxy 也很棒 |
最近基于 Proxy 写了一个库 memoizee-proxy,文章为 手写一个基于 Proxy 的缓存库 |
发现几处问题: 一: if (promise) { promise.push(promise) 是否应该为 -> promiseApi.push(promise) 🤔🤔🤔 二: (引用) 中, 秒和毫秒定义模糊,在上面代码中应该为 「设为多少毫秒」。 (引用) 中「使用 10s 缓存」,传参为 ExpiredCache.set(key, res, 10000)。 |
(一)是对的,我写错了 (二)我在超时判断除以了 1000 const overTime = (currentTime - data.cacheTime) / 1000 |
在这里用 proxy 的好处是什么? |
代理的价值是不改变原有的功能,也就是老函数依旧可以用,我可以根据需求使用 fibonacci 和 memoizedFibonacci 而不改变代码本身。 |
大佬已star 文章写得很不错啊,可以授权给公众号 深圳湾码农 转载吗?会注明作者及来源的,谢谢。 |
可以的 |
前端 api 请求缓存方案
在开发 web 应用程序时,性能都是必不可少的话题。对于webpack打包的单页面应用程序而言,我们可以采用很多方式来对性能进行优化,比方说 tree-shaking、模块懒加载、利用 extrens 网络cdn 加速这些常规的优化。甚至在vue-cli 项目中我们可以使用 --modern 指令生成新旧两份浏览器代码来对程序进行优化。
而事实上,缓存一定是提升web应用程序有效方法之一,尤其是用户受限于网速的情况下。提升系统的响应能力,降低网络的消耗。当然,内容越接近于用户,则缓存的速度就会越快,缓存的有效性则会越高。
以客户端而言,我们有很多缓存数据与资源的方法,例如 标准的浏览器缓存 以及 目前火热的 Service worker。但是,他们更适合静态内容的缓存。例如 html,js,css以及图片等文件。而缓存系统数据,我采用另外的方案。
那我现在就对我应用到项目中的各种 api 请求缓存方案,从简单到复杂依次介绍一下。
方案一 数据缓存
简单的 数据 缓存,第一次请求时候获取数据,之后便使用数据,不再请求后端api。
代码如下:
第一行代码 使用了 es6以上的 Map,如果对map不是很理解的情况下,你可以参考
ECMAScript 6 入门 Set 和 Map 或者 Exploring ES6 关于 map 和 set的介绍,此处可以理解为一个键值对存储结构。
之后 代码 使用 了 async 函数,可以将异步操作变得更为方便。 你可以参考ECMAScript 6 入门 async函数来进行学习或者巩固知识。
代码本身很容易理解,是利用 Map 对象对数据进行缓存,之后调用从 Map 对象来取数据。对于及其简单的业务场景,直接利用此代码即可。
调用方式:
方案二 promise缓存
方案一本身是不足的。因为如果考虑同时两个以上的调用此 api,会因为请求未返回而进行第二次请求api。当然,如果你在系统中添加类似于 vuex、redux这样的单一数据源框架,这样的问题不太会遇到,但是有时候我们想在各个复杂组件分别调用api,而不想对组件进行组件通信数据时候,便会遇到此场景。
该代码避免了方案一的同一时间多次请求的问题。同时也在后端出错的情况下对promise进行了删除,不会出现缓存了错误的promise就一直出错的问题。
调用方式:
方案三 多promise 缓存
该方案是同时需要 一个以上 的api请求的情况下,对数据同时返回,如果某一个api发生错误的情况下。均不返回正确数据。
该方案是同时获取多个服务器数据的方式。可以同时获得多个数据进行操作,不会因为单个数据出现问题而发生错误。
调用方式
方案四 添加时间有关的缓存
往往缓存是有危害的,如果我们在知道修改了数据的情况下,直接把 cache 删除即可,此时我们调用方法就可以向服务器进行请求。这样我们规避了前端显示旧的的数据。但是我们可能一段时间没有对数据进行操作,那么此时旧的数据就一直存在,那么我们最好规定个时间来去除数据。
该方案是采用了 类 持久化数据来做数据缓存,同时添加了过期时长数据以及参数化。
代码如下:
首先定义持久化类,该类可以存储 promise 或者 data
然后我们定义该数据缓存。我们采用Map 基本相同的api
此时数据类以及操作类 都已经定义好,我们可以在api层这样定义
该方案使用了 过期时间 和 api 参数不同而进行 缓存的方式。已经可以满足绝大部分的业务场景。
调用方式
方案五 基于修饰器的方案四
和方案四是的解法一致的,但是是基于修饰器来做。
代码如下:
此时 我们就会使用 类来对api进行缓存
因为函数存在函数提升,所以没有办法利用函数来做 修饰器
例如:
该代码意图是执行后counter等于 1,但是实际上结果是counter等于 0。因为函数提升,使得实际执行的代码是下面这样
所以没有 办法在函数上用修饰器。具体参考ECMAScript 6 入门 Decorator
此方式写法简单且对业务层没有太多影响。但是不可以动态修改 缓存时间
调用方式
总结
api的缓存机制与场景在这里也基本上介绍了,基本上能够完成绝大多数的数据业务缓存,在这里我也想请教教大家,有没有什么更好的解决方案,或者这篇博客中有什么不对的地方,欢迎指正,在这里感谢各位了。
同时这里也有很多没有做完的工作,可能会在后面的博客中继续完善。
The text was updated successfully, but these errors were encountered: