使用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的360图片展示实现代码
Jun 14 Javascript
Node.js(安装,启动,测试)
Jun 09 Javascript
详解Angular2中的编程对象Observable
Sep 17 Javascript
微信小程序 开发之滑块视图容器(swiper)详解及实例代码
Feb 22 Javascript
js实现延迟加载的几种方法
Apr 24 Javascript
教你用Cordova打包Vue项目的方法
Oct 17 Javascript
JavaScript设计模式之工厂模式简单实例教程
Jul 03 Javascript
对VUE中的对象添加属性
Sep 18 Javascript
小程序实现页面顶部选项卡效果
Nov 06 Javascript
js中的数组对象排序分析
Dec 11 Javascript
浅谈vue后台管理系统权限控制思考与实践
Dec 19 Javascript
15 分钟掌握vue-next响应式原理
Oct 13 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 的加密函数 md5,crypt,base64_encode 等使用介绍
2012/04/09 PHP
解析如何在PHP下载文件名中解决乱码的问题
2013/06/20 PHP
PHP 循环删除无限分类子节点的实现代码
2013/06/21 PHP
PHP实现自动登入google play下载app report的方法
2014/09/23 PHP
php内存缓存实现方法
2015/01/24 PHP
PHP简单实现DES加密解密的方法
2016/07/12 PHP
ThinkPHP like模糊查询,like多匹配查询,between查询,in查询,一般查询书写方法
2018/09/26 PHP
PHP模型Model类封装数据库操作示例
2019/03/14 PHP
JQuery页面的表格数据的增加与分页的实现
2013/12/10 Javascript
jquery中get,post和ajax方法的使用小结
2014/02/04 Javascript
使用jQuery jqPlot插件绘制柱状图
2014/12/18 Javascript
JS仿淘宝实现的简单滑动门效果代码
2015/10/14 Javascript
BootStrap实现鼠标悬停下拉列表功能
2017/02/17 Javascript
原生JS实现九宫格抽奖效果
2017/04/01 Javascript
详解如何构建一个Angular6的第三方npm包
2018/09/07 Javascript
详解vue组件之间的通信
2020/08/30 Javascript
js实现右键弹出自定义菜单
2020/09/08 Javascript
Python实现测试磁盘性能的方法
2015/03/12 Python
Python判断文件和文件夹是否存在的方法
2015/05/21 Python
Python实现模拟浏览器请求及会话保持操作示例
2018/07/30 Python
Python使用crontab模块设置和清除定时任务操作详解
2019/04/09 Python
python游戏开发之视频转彩色字符动画
2019/04/26 Python
Django使用模板后无法找到静态资源文件问题解决
2019/07/19 Python
一文轻松掌握python语言命名规范规则
2020/06/18 Python
HTML5新增属性data-*和js/jquery之间的交互及注意事项
2017/08/08 HTML / CSS
英国家喻户晓的家居商店:The Range
2019/03/25 全球购物
《荷花》教学反思
2014/04/16 职场文书
爱国主义教育活动总结
2014/05/07 职场文书
治庸问责心得体会
2014/09/12 职场文书
2014年领导班子专项整治整改方案
2014/09/28 职场文书
简单的离婚协议书范本
2014/11/16 职场文书
2014年业务工作总结
2014/11/17 职场文书
党员身份证明材料
2015/06/19 职场文书
python 如何在 Matplotlib 中绘制垂直线
2021/04/02 Python
Python anaconda安装库命令详解
2021/10/16 Python
Valheim服务器 Mod修改安装教程 【ValheimPlus】
2022/12/24 Servers