使用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 相关文章推荐
通过js来制作复选框的全选和不选效果
May 22 Javascript
jQuery在页面加载时动态修改图片尺寸的方法
Mar 20 Javascript
ztree获取选中节点时不能进入可视区域出现BUG如何解决
Dec 03 Javascript
浅谈javascript的call()、apply()、bind()的用法
Feb 21 Javascript
jquery弹出遮掩层效果【附实例代码】
Apr 28 Javascript
jquery validate表单验证插件
Sep 06 Javascript
使用Bootstrap美化按钮实例代码(demo)
Feb 03 Javascript
Vue keep-alive实践总结(推荐)
Aug 31 Javascript
jquery实现图片跟随鼠标的实例
Oct 17 jQuery
Vue实现导出excel表格功能
Mar 30 Javascript
原生js实现Flappy Bird小游戏
Dec 24 Javascript
帮你提高开发效率的JavaScript20个技巧
Jun 18 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实现框架(二)
2006/10/09 PHP
一篇入门的php Class 文章
2007/04/04 PHP
PHPMailer使用教程(PHPMailer发送邮件实例分析)
2012/12/06 PHP
PHP中常用的输出函数总结
2014/09/22 PHP
php微信公众平台开发类实例
2015/04/01 PHP
又十个超级有用的PHP代码片段
2015/09/24 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
jquery判断checkbox(复选框)是否被选中的代码
2010/10/20 Javascript
Extjs4 GridPanel 的几种样式使用介绍
2013/04/18 Javascript
jQuery ui插件的使用方法代码实例
2013/05/08 Javascript
javascript基本类型详解
2014/11/28 Javascript
javascript封装 Cookie 应用接口
2015/08/07 Javascript
bootstrap-datetimepicker实现只显示到日期的方法
2016/11/25 Javascript
express 项目分层实践详解
2018/12/10 Javascript
JavaScript对象的特性与实践应用深入详解
2018/12/30 Javascript
layui给下拉框、按钮状态、时间赋初始值的方法
2019/09/10 Javascript
用python简单实现mysql数据同步到ElasticSearch的教程
2018/05/30 Python
python操作excel文件并输出txt文件的实例
2018/07/10 Python
Python实现的简单计算器功能详解
2018/08/25 Python
python使用xlsxwriter实现有向无环图到Excel的转换
2018/12/12 Python
Python面向对象程序设计多继承和多态用法示例
2019/04/08 Python
10款最好的Python开发编辑器
2019/07/03 Python
Python openpyxl 插入折线图实例
2020/04/17 Python
python实现图片转换成素描和漫画格式
2020/08/19 Python
Numpy中np.random.rand()和np.random.randn() 用法和区别详解
2020/10/23 Python
Django admin组件的使用
2020/10/24 Python
Python基于unittest实现测试用例执行
2020/11/25 Python
Python日志打印里logging.getLogger源码分析详解
2021/01/17 Python
html5响应式开发自动计算fontSize的方法
2020/01/13 HTML / CSS
施华洛世奇新加坡官网:SWAROVSKI新加坡
2020/10/06 全球购物
GWT (Google Web Toolkit)有哪些主要的原件组成?
2015/06/08 面试题
应聘医药代表职位求职信
2013/10/21 职场文书
培训讲师岗位职责
2014/04/13 职场文书
建设投标担保书
2014/05/13 职场文书
父亲婚礼答谢词
2015/01/04 职场文书
2015年调度员工作总结
2015/04/30 职场文书