使用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 相关文章推荐
jquery 获取json数据实现代码
Apr 27 Javascript
Extjs中通过Tree加载右侧TabPanel具体实现
May 05 Javascript
ECMAScript6中Set/WeakSet详解
Jun 12 Javascript
JS实现的文字与图片定时切换效果代码
Oct 06 Javascript
javaScript基础详解
Jan 19 Javascript
jQuery EasyUI 组件加上“清除”功能实例详解
Apr 11 jQuery
JavaScript定义及输出螺旋矩阵的方法详解
Dec 01 Javascript
JS交互点击WKWebView中的图片实现预览效果
Jan 05 Javascript
深入解析ES6中的promise
Nov 08 Javascript
Vue分页器实现原理详解
Jun 28 Javascript
JS实现TITLE悬停长久显示效果完整示例
Feb 11 Javascript
原生JS实现无缝轮播图片
Jun 24 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
Discuz 模板引擎的封装类代码
2008/07/18 PHP
php采用file_get_contents代替使用curl实例
2014/11/07 PHP
ThinkPHP3.2框架使用addAll()批量插入数据的方法
2017/03/16 PHP
extjs DataReader、JsonReader、XmlReader的构造方法
2009/11/07 Javascript
JavaScript高级程序设计 阅读笔记(七) ECMAScript中的语句
2012/02/27 Javascript
ExtJs默认的字体大小改变的几种方法(自己整理)
2013/04/18 Javascript
JS 屏蔽按键效果与改变按键效果的示例代码
2013/12/24 Javascript
jquery模拟LCD 时钟的html文件源代码
2014/06/16 Javascript
js触发select onchange事件的小技巧
2014/08/05 Javascript
基于jquery实现表格内容筛选功能实例解析
2016/05/09 Javascript
微信小程序  action-sheet详解及实例代码
2016/11/09 Javascript
详解vuelidate 对于vueJs2.0的验证解决方案
2017/03/09 Javascript
zTree实现节点修改的实时刷新功能
2017/03/20 Javascript
jquery dataTable 后台加载数据并分页实例代码
2017/06/07 jQuery
实例详解Node.js 函数
2018/06/10 Javascript
解决vue attr取不到属性值的问题
2018/09/18 Javascript
浅谈layui使用模板引擎动态渲染元素要注意的问题
2019/09/14 Javascript
在layer弹层layer.prompt中,修改placeholder的实现方法
2019/09/27 Javascript
JS实现商城秒杀倒计时功能(动态设置秒杀时间)
2019/12/12 Javascript
如何手动实现一个 JavaScript 模块执行器
2020/10/16 Javascript
查看Python安装路径以及安装包路径小技巧
2015/04/28 Python
Ubuntu下升级 python3.7.1流程备忘(推荐)
2018/12/10 Python
python3使用QQ邮箱发送邮件
2020/05/20 Python
python3使用matplotlib绘制散点图
2019/03/19 Python
创建Django项目图文实例详解
2019/06/06 Python
Python使用APScheduler实现定时任务过程解析
2019/09/11 Python
Pytorch 计算误判率,计算准确率,计算召回率的例子
2020/01/18 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
2020/02/29 Python
django实现后台显示媒体文件
2020/04/07 Python
美国宠物护理专家:Revival Animal Health
2020/01/05 全球购物
大学自我鉴定
2013/12/20 职场文书
市场拓展计划书
2014/05/03 职场文书
售房委托书
2014/08/30 职场文书
六查六看心得体会
2014/10/14 职场文书
2015年中学校长工作总结
2015/05/19 职场文书
win10音频服务未响应怎么解决?win10音频服务未响应未修复的解决方法
2022/08/14 数码科技