阅读 4233

前端数据缓存(前端数据库)的一些见解,利用内存存储帮你优化接口请求

废话

钟离镇楼!

其实本身觉得这个没什么可以单独拿出来的,只是最近有点闲。但是这个技巧又非常实用。

1、写这篇文章的原因是因为我发现大家对于状态管理的误解(正确的是叫做数据管理或者说是前端数据库管理)

2、看到掘金有人发老梗,利用axios优化接口请求,取消重复请求。其实有更好的办法。

取消接口重复请求实际上是项目上有时候非常好的优化方式,但是又非常不好。具体看文章,哈哈

一、数据缓存的类型

1、localStorage

大小5M,文件存储级别,不清理浏览器缓存不消失

2、sessionStorage

大小5M,内存级别,但是当前标签页关闭则丢失

3、Cookie

按4097字节算吧,前端可以操作(后端可以定义不可操作的数据),但是一般由后端定义,并且现在新版的浏览器在逐步的抛弃该功能

4、IndexedDB

最小250M,文件级别(支持事务,属于websql的替代品),需要清理浏览器缓存才可以。一般用不到,主要是因为浏览器不做客户端的话那么就没什么用。做本地客户端可以用,比如electron

5、内存存储

就是变量存储,可以说是没有上线,取决于你的内存

6、……

其他还有webSql之类的,很多方式。主流的就上面这些

二、我平常项目如何使用这些存储的

1、常用情况或者说早期

在前端还没有太发展起来之前,其实前端存储数据应该都是以内存存储为主要方式。但是内存存储一刷新就没有了。

再后来浏览器除了cookie外,支持了sessionStorage、localStorage、websql等各种方式,前端才慢慢知道原来浏览器可以存储数据。这是前端面向客户端化的基础。

但是在很多前端初学者来说,都是直接拿着localStorage等api直接就上去怼。这个页面需要,我写一个,那个页面需要我写一个。项目越来越大,不知道哪里又写了一个。然后运行调试的时候发现把之前的存储给顶掉了。就像以前的var变量提升为全局变量一样,所以这样的前端是无法成为一个大项目的

2、从后端开发开发经历来思考前端存储(统一管理前端数据)

后端的存储其实比较好理解,内存存储,硬盘存储

然后转变为工具主要就是数据库,分为内存数据库和文件数据库。MySql属于文件数据库,redies属于内存级别。都是可查看,并且较为统一的。后端写数据之前都会先看数据库字段,然后再根据数据情况进行操作数据存储。但是前端那叫一个乱哦

那前端能不能也做一个统一的数据库呢?答案肯定是可以的

3、从现代化前端框架可以逆推前人项目(造轮子能力)

1、从react,vue框架上存储redux,vuex等等的前端状态管理,这是一个可聚合,可管理的js内存集合

ps:很多前端理解不够深刻的就把这当做状态管理了,吐槽那些不懂的管理层,前端和后端们。这难道不是天然的前端数据库吗

2、配合目前现有的插件,vuex持久化,redux持久化,这不就把状态库变成前端的数据库了么?

3、对项目进行约定规范

虽然解决了前端项目数据库的问题,但是需要有约定。约定大家在操作类似localStorage等api的时候不再可以直接写存储。必须接入vuex等能力,统一从vuex等状态库去操作数据。那么从数据存储的方面来看,就很清晰明了了。

4、逆推前人项目

关于redux和vuex等现代化框架来说,配合localStorage等持久化存储时非常方便的。但是没有redux和vuex呢?其实也很简单啊。

拿vuex来说,vuex是一个js文件,你定义这个js文件的数据存储的增删改查api,然后结合localStorage不就好了。

代码我就不写了,大神都懂,小白可以搜索《localStorage统一管理方案》。

vue项目vuex+vuex-persistedstate,所有数据操作走vuex

react项目redux+redux-persist,react方案特别多。vue走我上面推荐的就行了。

三、利用好变量,优化你的接口请求

重头戏来了,其实非常简单哦。

1、谈谈接口请求优化,取消重复请求

什么情况下会出现重复请求呢?

手抖了,不小心连续请求两次。老项目,有一个数据接口,比如分类接口,好多地方要用。

第一个情况其实应该用节流防抖等设计模式去解决。第二种呢?这不是异常,应该要这么做。

2、取消重复请求的缺点

如果是一个新项目,那么你需要的数据接口请求很少。自然也就不不太会发生这种情况。但是你一个老项目怎么办呢?

亲身举例:之前在云问做一个两年的老前端项目。也许初始项目很小,没有这些问题。但是随着项目越来越大,页面中存在几个基本数据获取接口。比如省市区,比如分类还有权限等等。之前同事“咔”一刀,利用axios中间拦截能力把重复请求的直接砍掉。好吗,项目多处直接功能瘫痪。无奈为了业务放弃性能优化。

3、利用前端数据库能力提前缓存好接口数据,存储在vuex等地方

这个想法非常好的,但是之前的人没用这一套,你接入这套管理方案的成本是至少三个js文件的改动级别。你怎么办呢?

4、巧妙利用js文件和声明变量

原理:js内存变量能力和js文件缓存能力

1、首先你声明的变量需要放在一个js文件中进行导出,你会发现你到处都可以获取到这个文件中存储的变量值。那你修改之后是不是也可以拿到修改之后的值呢?

2、把这种基础的短时间不会变化数据的接口数据,在请求之后把数据存入js文件的变量中,当重复请求的时候,判断变量是否有值,有就直接取值。那是不是接口下次请求进来就不会在走后台接口呢?

5、实践代码(项目中拎出来的代码)

这是我一个项目中的代码,其中有一个地方是一个级联组件。组件需要选择视频数据,剧本数据。级联组件使用的地方非常多。但是每次都加载组件都会导致接口请求数据,那么问题就大了。用户会觉得很卡。说实在产品都没想到,我自己加的功能。唉

代码为vue2代码方式

首先声明一个store.js文件

import Vue from 'vue'

const Store = Vue.observable({
  AllVideo: new Map(), // 所有视频,性能优化, 存在数据情况这里取数据
  AllDrama: new Map(), // 所有剧本,性能优化
 
})

const Mutations = {
  // 重置数据
  restData() {
    Store.AllDrama = new Map()
    Store.AllDrama = new Map()
  },
}

export { Store, Mutations }
复制代码

在级联组件中导入函数

import { Store } from 'store'
复制代码

组件部分,干掉多余逻辑和处理,呈现一个较为简单的结构给大家

<script>

import { Store } from '../store'

export default {
  data() {
    return {}
  },
  methods: {
    // 获取所有视频
    async getAllVideo() {
      try {
        let materialType = this.materialType
        materialType = materialType === 3 ? 2 : this.materialType
        // 如果内存中存在数据则直接返回,不走接口请求数据
        const typeData = Store.AllVideo.get(materialType)
        if (typeData) return Promise.resolve(typeData)
        // 请求接口
        const result = await Service.VideoServer.videoList({
          data: {
            corpId: this.$store.state.userInfo.corpid,
            filterStatus: [1],
            page: 1,
            size: 2000,
          },
        })
        const records = result.data.records ?? []
        //第一次请求的情况下同时把数据存入到js文件的变量中
        Store.AllVideo.set(materialType, videoList)
        return Promise.resolve(videoList)
      } catch (e) {
        return Promise.reject(e)
      }
    },
  },
}
</script>
复制代码

6、注意事项

实际上就这么简单,页面上就很容易的把请求优化掉了。还不会产生全局不良影响。

注意点:主要就是这个属于你自己额外开辟的存储,属于内存存储,随着刷新就丢失。但是在不刷新页面的情况下存储会一直驻留在页面的内存中。注意使用,别引发内存泄露问题。

四、感谢看到这里的读者们

文章分类
前端
文章标签