使用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 相关文章推荐
JavaScript Cookie的读取和写入函数
Dec 08 Javascript
javascript 系统文件夹文件操作及参数介绍
Jan 08 Javascript
一个简单的瀑布流效果(主体形式自写)
May 27 Javascript
js格式化金额可选是否带千分位以及保留精度
Jan 28 Javascript
JavaScript简单实现鼠标移动切换图片的方法
Feb 23 Javascript
你不需要jQuery(三) 新AJAX方法fetch()
Jun 14 Javascript
关于JS 预解释的相关理解
Jun 28 Javascript
jquery学习笔记之无new构建详解
Dec 07 jQuery
vue中的自定义分页插件组件的示例
Aug 18 Javascript
React Native 混合开发多入口加载方式详解
Sep 23 Javascript
详解JavaScript修改注册表的方法
Jan 05 Javascript
小程序表单认证布局及验证详解
Jun 19 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 shell命令合并图片的代码
2011/06/23 PHP
查找php配置文件php.ini所在路径的二种方法
2014/05/26 PHP
php实现过滤表单提交中html标签的方法
2014/10/17 PHP
PHP改进计算字符串相似度的函数similar_text()、levenshtein()
2014/10/27 PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
2016/10/10 PHP
laravel框架模型、视图与控制器简单操作示例
2019/10/10 PHP
javascript 二分法(数组array)
2010/04/24 Javascript
将nodejs打包工具整合到鼠标右键的方法
2013/05/11 NodeJs
JavaScript点击按钮后弹出透明浮动层的方法
2015/05/11 Javascript
JS实现自动变化的导航菜单效果代码
2015/09/09 Javascript
Web安全测试之XSS实例讲解
2016/08/15 Javascript
node+experss实现爬取电影天堂爬虫
2016/11/20 Javascript
微信小程序开发之录音机 音频播放 动画实例 (真机可用)
2016/12/08 Javascript
jquery表单提交带错误信息提示效果
2017/03/09 Javascript
JavaScript的六种继承方式(推荐)
2017/06/26 Javascript
SpringMVC简单整合Angular2的示例
2017/07/31 Javascript
React中使用外部样式的3种方式(小结)
2019/05/28 Javascript
详解基于Wepy开发小程序插件(推荐)
2019/08/01 Javascript
VuePress 中如何增加用户登录功能
2019/11/29 Javascript
详谈Vue.js框架下main.js,App.vue,page/index.vue之间的区别
2020/08/12 Javascript
详解python上传文件和字符到PHP服务器
2017/11/24 Python
python 如何设置守护进程
2020/10/29 Python
python tkinter实现下载进度条及抖音视频去水印原理
2021/02/07 Python
HTML5开发动态音频图的实现
2020/07/02 HTML / CSS
阿根廷票务网站:StubHub阿根廷
2018/04/13 全球购物
100%有机精油,美容油:House of Pure Essence
2018/10/30 全球购物
幼儿园庆六一游园活动方案
2014/01/29 职场文书
快餐店的创业计划书范文
2014/01/29 职场文书
新员工入职感言
2014/02/01 职场文书
大学生职业规划书的范本
2014/02/18 职场文书
房屋公证委托书
2014/04/03 职场文书
二年级上册数学教学计划
2015/01/20 职场文书
安阳殷墟导游词
2015/02/10 职场文书
党风廉政建设个人总结
2015/03/06 职场文书
实习单位意见
2015/06/04 职场文书
学习型家庭事迹材料(2016精选版)
2016/02/29 职场文书