使用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 相关文章推荐
初学prototype,发个JS接受URL参数的代码
Sep 25 Javascript
js几个不错的函数 $$()
Oct 09 Javascript
js/jQuery对象互转(快速操作dom元素)
Feb 04 Javascript
推荐JavaScript实现继承的最佳方式
Nov 11 Javascript
JavaScript检测实例属性, 原型属性
Feb 04 Javascript
angularjs学习笔记之简单介绍
Sep 26 Javascript
基于slideout.js实现移动端侧边栏滑动特效
Nov 28 Javascript
使用ECharts实现状态区间图
Oct 25 Javascript
layer.js open 隐藏滚动条的例子
Sep 05 Javascript
javascript用defineProperty实现简单的双向绑定方法
Apr 03 Javascript
vue-cli或vue项目利用HBuilder打包成移动端app操作
Jul 29 Javascript
原生js拖拽功能制作滑动条实例代码
Feb 05 Javascript
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
php安全开发 添加随机字符串验证,防止伪造跨站请求
2013/02/14 PHP
深入理解JavaScript系列(12) 变量对象(Variable Object)
2012/01/16 Javascript
jQuery响应鼠标事件并隐藏与显示input默认值
2014/08/24 Javascript
javascript操作ul中li的方法
2015/05/14 Javascript
jQuery 选择器(61种)整理总结
2016/09/26 Javascript
JSON对象 详解及实例代码
2016/10/18 Javascript
jQuery插件echarts实现的循环生成图效果示例【附demo源码下载】
2017/03/04 Javascript
使用canvas及js简单生成验证码方法
2017/04/02 Javascript
jQuery绑定事件方法及区别(bind,click,on,live,one)
2017/08/14 jQuery
jQuery实现的滑块滑动导航效果示例
2018/06/04 jQuery
微信小程序倒计时功能实例代码
2018/07/17 Javascript
使用kbone解决Vue项目同时支持小程序问题
2019/11/08 Javascript
Vue使用Ref跨层级获取组件的步骤
2021/01/25 Vue.js
Vue中的nextTick作用和几个简单的使用场景
2021/01/25 Vue.js
[02:20]DOTA2亚洲邀请赛 IG战队出场宣传片
2015/02/07 DOTA
教大家使用Python SqlAlchemy
2016/02/12 Python
python简单图片操作:打开\显示\保存图像方法介绍
2017/11/23 Python
使用python获取电脑的磁盘信息方法
2018/11/01 Python
Python实现定时执行任务的三种方式简单示例
2019/03/30 Python
python getpass模块用法及实例详解
2019/10/07 Python
pyftplib中文乱码问题解决方案
2020/01/11 Python
python3光学字符识别模块tesserocr与pytesseract的使用详解
2020/02/26 Python
一篇文章搞懂python的转义字符及用法
2020/09/03 Python
python3中calendar返回某一时间点实例讲解
2020/11/18 Python
python邮件中附加文字、html、图片、附件实现方法
2021/01/04 Python
基于PyInstaller各参数的含义说明
2021/03/04 Python
维多利亚的秘密官方旗舰店:VICTORIA’S SECRET
2018/04/02 全球购物
Omio葡萄牙:全欧洲低价大巴、火车和航班搜索和比价
2019/02/09 全球购物
个人自我评价分享
2013/12/20 职场文书
青年教师培训方案
2014/02/06 职场文书
安全生产责任书范本
2014/04/15 职场文书
《鹬蚌相争》教学反思
2014/04/22 职场文书
信用社主任竞聘演讲稿
2014/05/23 职场文书
商务日语专业的自荐信
2014/05/23 职场文书
运动会加油稿30字
2015/07/21 职场文书
Python编程根据字典列表相同键的值进行合并
2021/10/05 Python