使用vuex缓存数据并优化自己的vuex-cache


Posted in Javascript onMay 30, 2018

需求:

  1. 请求接口之后,缓存当前接口的数据,下次请求同一接口时拿缓存数据,不再重新请求
  2. 添加缓存失效时间

cache使用map来实现

ES6 模块与 CommonJS 模块的差异

  1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

因为esm输出的是值的引用,直接就是单例模式了

详细

export let cache = new Cache()

版本1

思路:

  1. 在vuex注册插件,插件会在每次mutations提交之后,判断要不要写入cache
  2. 在提交actions的时候判断是否有cache,有就拿cache里面的数据,然后把数据commit给mutataios

注意: 在插件里面获取的mutations-type是包含命名空间的,而在actions里面则是没有命名空间,需要补全。

/mutation-types.js

/**
 * 需要缓存的数据会在mutations-type后面添加-CACHED
 */
export const SET_HOME_INDEX = 'SET_HOME_INDEX-CACHED'
/modules/home/index.js


const actions = {
 /**
  * @description 如果有缓存,就返回把缓存的数据,传入mutations,
  * 没有缓存就从接口拿数据,存入缓存,把数据传入mutations
  */
 async fetchAction ({commit}, {mutationType, fetchData, oPayload}) {
  // vuex开启了命名空间,所这里从cachekey要把命名空间前缀 + type + 把payload格式化成JSON
  const cacheKey = NAMESPACE + mutationType + JSON.stringify(oPayload)
  const cacheResponse = cache.get(cacheKey || '')
  if (!cacheResponse) {
   const [err, response] = await fetchData()
   if (err) {
    console.error(err, 'error in fetchAction')
    return false
   }
   commit(mutationType, {response: response, oPayload})
  } else {
   console.log('已经进入缓存取数据!!!')
   commit(mutationType, {response: cacheResponse, oPayload})
  }
 },
 loadHomeData ({ dispatch, commit }) {
  dispatch(
   'fetchAction',
   {
    mutationType: SET_HOME_INDEX,
    fetchData: api.index,
   }
  )
 }
}

const mutations = {
 [SET_HOME_INDEX] (state, {response, oPayload}) {},
}

const state = {
 indexData: {}
}

export default {
 namespaced: NAMESPACED,
 actions,
 state,
 getters,
 mutations
}

编写插件,在这里拦截mutations,判断是否要缓存
/plugin/cache.js

import cache from 'src/store/util/CacheOfStore'
// import {strOfPayloadQuery} from 'src/store/util/index'
/**
 * 在每次mutations提交之后,把mutations-type后面有CACHED标志的数据存入缓存,
 * 现在key值是mutations-type
 * 问题:
 * 没办法区分不同参数query的请求,
 *
 * 方法1: 用每个mutations-type + payload的json格式为key来缓存数据
 */
function cachePlugin () {
 return store => {
  store.subscribe(({ type, payload }, state) => {
   // 需要缓存的数据会在mutations-type后面添加CACHED
   const needCache = type.split('-').pop() === 'CACHED'
   if (needCache) {
    // 这里的type会自动加入命名空间所以 cacheKey = type + 把payload格式化成JSON
    const cacheKey = type + JSON.stringify(payload && payload.oPayload)
    const cacheResponse = cache.get(cacheKey)
    // 如果没有缓存就存入缓存
    if (!cacheResponse) {
     cache.set(cacheKey, payload.response)
    }
   }
   console.log(cache)
  })
 }
}
const plugin = cachePlugin()
export default plugin

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import home from './modules/home'
import cachePlugin from './plugins/cache'

Vue.use(Vuex)
const store = new Vuex.Store({
 modules: {
  home,
  editActivity,
  editGuide
 }
 plugins: [cachePlugin]
})

export default store

版本2

思路:直接包装fetch函数,在里面里面判断是否需要缓存,缓存是否超时。

优化点:

  1. 把原本分散的cache操作统一放入到fetch
  2. 减少了对命名空间的操作
  3. 添加了缓存有效时间

/actions.js

const actions = {
 async loadHomeData ({ dispatch, commit }, oPayload) {
  commit(SET_HOME_LOADSTATUS)
  const [err, response] = await fetchOrCache({
   api: api.index,
   queryArr: oPayload.queryArr,
   mutationType: SET_HOME_INDEX
  })
  if (err) {
   console.log(err, 'loadHomeData error')
   return [err, response]
  }
  commit(SET_HOME_INDEX, { response })
  return [err, response]
 }
}

在fetchOrCache判断是需要缓存,还是请求接口

/**
 * 用这个函数就说明是需要进入缓存
 * @param {*} api 请求的接口
 * @param {*} queryArr 请求的参数
 * @param {*} mutationType 传入mutationType作为cache的key值
 */
export async function fetchOrCache ({api, queryArr, mutationType, diff}) {
 // 这里是请求接口
 const fetch = httpGet(api, queryArr)
 const cachekey = `${mutationType}:${JSON.stringify(queryArr)}`
 if (cache.has(cachekey)) {
  const obj = cache.get(cachekey)
  if (cacheFresh(obj.cacheTimestemp, diff)) {
   return cloneDeep(obj)
  } else {
   // 超时就删除
   cache.delete(cachekey)
  }
 }
 // 不取缓存的处理
 let response = await fetch()
 // 时间戳绑定在数组的属性上
 response.cacheTimestemp = Date.now()
 cache.set(cachekey, response)
 // 返回cloneDeep的对象
 return cloneDeep(response)
}
/**
 * 判断缓存是否失效
 * @param {*} diff 失效时间差,默认15分钟=900s
 */
const cacheFresh = (cacheTimestemp, diff = 900) => {
 if (cacheTimestemp) {
  return ((Date.now() - cacheTimestemp) / 1000) <= diff
 } else {
  return true
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 控制弹出窗口
Apr 10 Javascript
《JavaScript高级编程》学习笔记之object和array引用类型
Nov 01 Javascript
JS提交form表单实例分析
Dec 10 Javascript
Mongoose学习全面理解(推荐)
Jan 21 Javascript
js监听input输入框值的实时变化实例
Jan 26 Javascript
JavaScript字符集编码与解码详谈
Feb 02 Javascript
原生js实现简单的模态框示例
Sep 08 Javascript
微信小程序分享海报生成的实现方法
Dec 10 Javascript
微信小程序实现同一页面取值的方法分析
Apr 30 Javascript
Vue+element+cookie记住密码功能的简单实现方法
Sep 20 Javascript
原生JavaScript实现随机点名表
Jan 14 Javascript
Vue+Bootstrap实现简易学生管理系统
Feb 09 Vue.js
vue源码学习之Object.defineProperty 对数组监听
May 30 #Javascript
vue源码学习之Object.defineProperty对象属性监听
May 30 #Javascript
Angular搜索场景中使用rxjs的操作符处理思路
May 30 #Javascript
微信小程序实现跑马灯效果完整代码(附效果图)
May 30 #Javascript
vue通过点击事件读取音频文件的方法
May 30 #Javascript
vue 表单输入格式化中文输入法异常问题
May 30 #Javascript
详解如何使用babel进行es6文件的编译
May 29 #Javascript
You might like
Windows下的PHP 5.3.x安装 Zend Guard Loader教程
2014/09/06 PHP
ThinkPHP实现支付宝接口功能实例
2014/12/02 PHP
学习php设计模式 php实现享元模式(flyweight)
2015/12/07 PHP
Smarty分页实现方法完整实例
2016/05/11 PHP
form自动提交实例讲解
2017/07/10 PHP
jquery下json数组的操作实现代码
2010/08/09 Javascript
jquery获取节点名称
2015/04/26 Javascript
JS代码实现table数据分页效果
2016/05/26 Javascript
bootstrap的3级菜单样式,支持母版页保留打开状态实现方法
2016/11/10 Javascript
zTree节点文字过多的处理方法
2017/11/24 Javascript
vue-cli 3.x 配置Axios(proxyTable)跨域代理方法
2018/09/19 Javascript
微信小程序非swiper组件实现的自定义伪3D轮播图效果示例
2018/12/11 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
2019/06/19 jQuery
基于vue hash模式微信分享#号的解决
2020/09/07 Javascript
JS实现密码框效果
2020/09/10 Javascript
Python Tkinter简单布局实例教程
2014/09/03 Python
Python更新数据库脚本两种方法及对比介绍
2017/07/27 Python
利用Python进行异常值分析实例代码
2017/12/07 Python
python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)
2017/12/20 Python
TensorFlow 模型载入方法汇总(小结)
2018/06/19 Python
pyspark.sql.DataFrame与pandas.DataFrame之间的相互转换实例
2018/08/02 Python
详解Python Qt的窗体开发的基本操作
2019/07/14 Python
详解用python生成随机数的几种方法
2019/08/04 Python
python动态视频下载器的实现方法
2019/09/16 Python
python GUI库图形界面开发之PyQt5菜单栏控件QMenuBar的详细使用方法与实例
2020/02/28 Python
解决windows上安装tensorflow时报错,“DLL load failed: 找不到指定的模块”的问题
2020/05/20 Python
HTML5 背景的显示区域实现
2020/07/09 HTML / CSS
波兰品牌内衣及泳装网上商店:Astratex.pl
2017/02/03 全球购物
美国背景检查、公共记录和人物搜索网站:BeenVerified
2018/02/25 全球购物
Casetify官网:自制专属手机壳、iPad护壳和Apple Watch手表带
2018/05/09 全球购物
美国体育用品在线:Modell’s Sporting Goods
2018/06/07 全球购物
加拿大时装零售商:Influence U
2018/12/22 全球购物
荷兰照明、灯具和配件网上商店:dmlights
2019/08/25 全球购物
怎样在 Applet 中建立自己的菜单(MenuBar/Menu)?
2012/06/20 面试题
个人应聘自我评价分享
2013/11/18 职场文书
董事长年会致辞
2015/07/29 职场文书