使用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 input 数字验证代码
Jul 30 Javascript
Ajax执行顺序流程及回调问题分析
Dec 10 Javascript
谈谈关于JavaScript 中的 MVC 模式
Apr 11 Javascript
jQuery 复合选择器应用的几个例子
Sep 11 Javascript
jquery实现仿JqueryUi可拖动的DIV实例
Jul 31 Javascript
JS动态计算移动端rem的解决方案
Oct 14 Javascript
Jquery中.bind()、.live()、.delegate()和.on()之间的区别详解
Aug 01 jQuery
node.js 用socket实现聊天的示例代码
Oct 17 Javascript
node.js使用免费的阿里云ip查询获取ip所在地【推荐】
Sep 03 Javascript
vue移动端下拉刷新和上拉加载的实现代码
Sep 08 Javascript
Vue 使用formData方式向后台发送数据的实现
Apr 14 Javascript
layer.prompt使文本框为空的情况下也能点击确定的方法
Sep 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
解析如何屏蔽php中的phpinfo()函数
2013/06/06 PHP
php 字符串中的\n换行符无效、不能换行的解决方法
2014/04/02 PHP
微信公众平台天气预报功能开发
2014/07/06 PHP
php查找字符串中第一个非0的位置截取
2017/02/27 PHP
JavaScript对象模型-执行模型
2008/04/28 Javascript
页面加载完成后再执行JS的jquery写法以及区别说明
2014/02/22 Javascript
jQuery遍历页面所有CheckBox查看是否被选中的方法
2015/04/14 Javascript
jQuery实现可拖拽的许愿墙效果【附demo源码下载】
2016/09/14 Javascript
原生js实现可爱糖果数字时间特效
2016/12/30 Javascript
Nodejs实现文件上传的示例代码
2017/09/26 NodeJs
弱类型语言javascript中 a,b 的运算实例小结
2019/08/07 Javascript
haskell实现多线程服务器实例代码
2013/11/26 Python
python统计日志ip访问数的方法
2015/07/06 Python
使用Python编写爬虫的基本模块及框架使用指南
2016/01/20 Python
python的变量与赋值详细分析
2017/11/08 Python
python简单图片操作:打开\显示\保存图像方法介绍
2017/11/23 Python
Python实现基于C/S架构的聊天室功能详解
2018/07/07 Python
Pyqt5如何让QMessageBox按钮显示中文示例代码
2019/04/11 Python
详解pandas使用drop_duplicates去除DataFrame重复项参数
2019/08/01 Python
Python 实现递归法解决迷宫问题的示例代码
2020/01/12 Python
HTML5实现晶莹剔透的雨滴特效
2014/05/14 HTML / CSS
英国老牌潮鞋店:Offspring
2019/08/19 全球购物
美国环保妈妈、儿童和婴儿用品购物网站:The Tot
2019/11/24 全球购物
Harman Audio官方商店:购买JBL、Harman Kardon、Infinity和AKG
2019/12/05 全球购物
天网面试题
2013/04/07 面试题
sealed修饰符是干什么的
2012/10/23 面试题
Python是如何进行类型转换的
2013/06/09 面试题
历史学专业推荐信
2013/11/06 职场文书
副厂长岗位职责
2014/02/02 职场文书
统计系教授推荐信
2014/02/28 职场文书
2014年汽车销售工作总结
2014/12/01 职场文书
小学母亲节活动总结
2015/02/10 职场文书
2015年车间管理工作总结
2015/07/23 职场文书
2015年法律事务部工作总结
2015/07/27 职场文书
python中的被动信息搜集
2021/04/29 Python
基于Python实现将列表数据生成折线图
2022/03/23 Python