博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第四篇:小程序之缓存策略
阅读量:6795 次
发布时间:2019-06-26

本文共 8711 字,大约阅读时间需要 29 分钟。

缓存key分为内存缓存和本地缓存。如果是持久化的,需要缓存到本地中。但是,小程序中对于一些特殊结构的对象,如Map、Set的缓存是不支持的。那如果非要缓存呢,该如何实现呢?且听我娓娓道来。

一、内存缓存

java中,内存缓存经常用到的是集合,List、Set、Map、数组 等。那么小程序都有啥呢?答案是数组、Set、Map集合,没有List集合。当然,此Map非java中的那个Map,java中Map是个抽象类, 具体的实现类是HashMap、LinkedHashMap等。 首先来介绍下小程序中的Set、Map基本上使用

1、Set

去除重复成员的缓存容器

(1)Set实例化

const s = new Set();Set 函数可以接受一个数组const set = new Set([1, 2, 3, 4, 4]);复制代码

(2)api介绍

add(value):添加某个值,返回 Set 结构本身。    delete(value):删除某个值,返回一个布尔值,表示删除是否成功。    has(value):返回一个布尔值,表示该值是否为Set的成员。    clear():清除所有成员,没有返回值。    Array.from方法可以将 Set 结构转为数组。复制代码

(3)Set遍历

keys():返回键名的遍历器    values():返回键值的遍历器    entries():返回键值对的遍历器    forEach():使用回调函数遍历每个成员复制代码

示例:

let set = new Set(['red', 'green', 'blue']);for (let item of set.keys()) {  console.log(item);}// red// green// bluefor (let item of set.values()) {  console.log(item);}// red// green// bluefor (let item of set.entries()) {  console.log(item);}// ["red", "red"]// ["green", "green"]// ["blue", "blue"]/*** 直接用for...of循环遍历(常规)*/for (let x of set) {  console.log(x);}// red// green// blue//forEach的遍历set = new Set([1, 4, 9]);set.forEach((value, key) => console.log(key + ' : ' + value))// 1 : 1// 4 : 4// 9 : 9复制代码

2、Map

key-value 键值对形式。 key:的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,

(1)Map的api介绍

const map = new Map([  ['name', '张三'],  ['title', 'Author']]);map.set('edition', 6)        // 键是字符串map.set(262, 'standard')     // 键是数值map.set(undefined, 'nah')    // 键是 undefinedmap.size // 2map.has('name') // truemap.get('name') // "张三"map.has('title') // truemap.get('title') // "Author"map.clear()map.size // 0复制代码

(2)Map的遍历

keys():返回键名的遍历器。    values():返回键值的遍历器。    entries():返回所有成员的遍历器。    forEach():遍历 Map 的所有成员。复制代码

示例:

const map = new Map([  ['F', 'no'],  ['T',  'yes'],]);for (let key of map.keys()) {  console.log(key);}// "F"// "T"for (let value of map.values()) {  console.log(value);}// "no"// "yes"for (let item of map.entries()) {  console.log(item[0], item[1]);}// "F" "no"// "T" "yes"// 或者for (let [key, value] of map.entries()) {  console.log(key, value);}// "F" "no"// "T" "yes"// 等同于使用map.entries()for (let [key, value] of map) {  console.log(key, value);}// "F" "no"// "T" "yes"复制代码

注意:

1、Map 结构转为数组结构

const map = new Map([  [1, 'one'],  [2, 'two'],  [3, 'three'],]);[...map.keys()]// [1, 2, 3][...map.values()]// ['one', 'two', 'three'][...map.entries()]// [[1,'one'], [2, 'two'], [3, 'three']][...map]// [[1,'one'], [2, 'two'], [3, 'three']]复制代码

2、数组 转为 Map

new Map([  [true, 7],  [{foo: 3}, ['abc']]])复制代码

3、Map 转为 JSON

JSON.stringify(strMapToObj(strMap));//Map 转为对象function strMapToObj(strMap) {  let obj = Object.create(null);  for (let [k,v] of strMap) {    obj[k] = v;  }  return obj;}复制代码

4、JSON 转为 Map

objToStrMap(JSON.parse(jsonStr))//对象转为 Mapfunction objToStrMap(obj) {  let strMap = new Map();  for (let k of Object.keys(obj)) {    strMap.set(k, obj[k]);  }  return strMap;}复制代码

3、数组

二、本地缓存

还是先来看下官网的列子:

同步缓存:try {	wx.setStorageSync('key', 'value')} catch (e) {	}复制代码
异步缓存wx.setStorage({  key:"key",  data:"value"})复制代码

我想说的是,setStorageSync能直接缓存Map、Set集合吗?很不幸的是,答案不可用。但是可以缓存数组。那么如果非要缓存呢? 本文的核心来了。 经过处理后,本地缓存形式结构如下图:

1、缓存map含数组的集合

由于小程序setStorageSync只支持缓存String和对象(非集合),所以存的时候回,将map转为String。取的时候,将String转为Map

解决思路:

  • 1、先遍历需要缓存的集合cacheMap,得到key和value
  • 2、将value集合转为数组valueArray
  • 3、新建一个Map集合tempMap,存入数据,且key是需要缓存集合cacheMap的key,value是被转换的数组valueArray
  • 4、将tempMap集合转换为tempArray数组
  • 5、然后将tempArray数组通过JSON.stringify(tempArray),转换为String字符串cacheString
  • 6、最后将字符串cacheString缓存到缓存中,完成Map转换为String的缓存转换

注意:

1、由于小程序无法直接缓存map集合,也无法缓存Set集合,只能缓存字符串。所以最终需要将对Map集合的缓存,转变为String的缓存 2、由于JSON.stringify方法只支持将数组转换为String,所以,要在将Map转为String之前,必须将要缓存的集合cacheMap原来的value(Set集合)转为数组 3、支持如 map<String,object>、map<String,Set<String>>、map<String,Set<Bean>> 不支持双层Map集合,如Map<String,Map<?>>

具体实现代码:

/**  isNestedFlage: 嵌套类的复杂Map集合 *              true ,缓存缓存map含数组的集合,如 map
>、map
> * false: 缓存Map
Map
、 Map
、Map
(Bean是object的实体类) * /export function cacheMap(cacheKey, cacheMap, isSync = true) { if (cacheMap == null || cacheMap.length == 0 || !cacheKey) { return false; } if (tempMap == null) { tempMap = new Map() } else { tempMap.clear() } let isNestedFlage = false; cacheMap.forEach(function (value, key, cacheMap) { console.log("Key: %s, Value: %s", key, value); if (Object.getPrototypeOf(value) == Array.prototype || Object.getPrototypeOf(value) == Set.prototype) { //将value 数组 var valueArray = Array.from(value) // // 将数组转换为一个json字符串 tempMap.set(key, valueArray) isNestedFlage = true } }); if (!isNestedFlage) { tempMap = cacheMap } // 将Map集合转为数组 var tempArray = [...tempMap] var cacheString = JSON.stringify(tempArray) cacheKeyAndValue(cacheKey, cacheString, isSync)}复制代码

2、取缓存map

对于含单例集合,如map<String,Set<String>>、map<String,Object>

思路:

  • 1、先根据cacheKey获取缓存信息cacheMapInfo
  • 2、将获取缓存信息cacheMapInfo转换为字符串cacheMapStr
  • 3、将字符串转为Map集合tempCacheMap
  • 4、由于原来缓存Map集合时,将Set集合转为了数组,所以,这里也要对数组还原成Set集合。因此,遍历tempCacheMap,将其value值(即数组),转换为Set集合
  • 5、最后将tempCacheMap集合遍历转换的结果存入cacheMap集合中,并且返回

注意:

由于原来缓存Map集合时,将Set集合转为了数组,所以,这里一定要要对缓存转换后的Map集合tempCacheMap的value值(数组)还原成Set集合

具体代码实现:

export function getCacheMap(cacheKey, isSync = true) {  if (!cacheKey) {    return new Map();  }  var cacheMapInfo = getCacheValue(cacheKey)  if (!cacheMapInfo) {    return new Map();  }  var cacheMapStr = JSON.parse(cacheMapInfo)  // 字符串转换为Map集合  var tempCacheMap = util.objToMap(cacheMapStr)  let cacheMap  if (cacheMap == null) {    cacheMap = new Map()  } else {    cacheMap.clear()  }  tempCacheMap.forEach(function (value, key, tempCacheMap) {    console.log("===Key: %s, Value: %s", key, value);    var mapKey = value[0];    if (Object.getPrototypeOf(value[1]) == Set.prototype || Object.getPrototypeOf(value[1]) == Array.prototype) {      // 由于原来缓存Map集合时,将Set集合转为了数组,所以,这里也要对数组还原成Set集合      var mapValue = new Set(value[1]);      cacheMap.set(mapKey, mapValue)    } else if (Object.getPrototypeOf(value[1]) == Map.prototype) {      throw new Error("数据格式错误,暂时不支持Mvalue是Map的结果")    } else {  //number、string、boolean、Object对象类型      cacheMap.set(value[0], value[1])    }  });  return cacheMap;}复制代码

3、缓存数组、Set

  • 1、支持数组Array集合、和Set集合
  • 2、支持简单数据类型(Array、Set),如 set<Integer>、set<Boolean>、set<String>、set<Array>、set<Bean>(Bean是object的实体类)
  • 3、支持复杂数据类型(Array、Set),如 set<Set<?>>、 set<Array<?>>、set<Set<Set<?>>、set<Set<Array<?>>> 、 set<Array<Set<?>>>

代码实现如下:

// isSync true 同步缓存。且默认是true,同步缓存export function cacheArray(cacheKey, cacheArray, isSync = true) {  if (cacheArray == null || cacheArray.length == 0 || !cacheKey) {    return false;  }  let realCacheArray = util.setToArray(cacheArray)  var cacheString = JSON.stringify(realCacheArray)  cacheKeyAndValue(cacheKey, cacheString, isSync)}复制代码

4、获取Set,同样适合数组

export function getCacheArray(cacheKey, callback = null) {  if ((callback && typeof (callback) === "function")){    var cacheInfoSync = getCacheValue(cacheKey, function (cacheInfo) {      if ((callback && typeof (callback) === "function") && cacheInfo) {   //异步        let cacheArray = JSON.parse(cacheInfo)        callback(cacheArray)      }    });  }else{    var result = getCacheValue(cacheKey)    let realResult    if (result == "undefined" || result == null || result == ""){  //如果返回的是空串、或者是之前未缓存的对象,这里默认是返回空数组      realResult = []    }else{      realResult = JSON.parse(result)    }    return realResult  }}复制代码

5、Object对象的缓存

思路: 遍历对象,获取每个属性名key,和属性值value,然后逐一缓存每个属性值

export function cacheValue(cacheInfo, isSync = true) {  if (!cacheInfo) { //cacheInfo = null 、""    return false;  }  //遍历对象,获取每个属性名key,和属性值value,然后逐一缓存每个属性值  for (var propertyName in cacheInfo) {    if (!propertyName) {      break;    }    try {      var cacheKey = "key_" + propertyName      if (isSync) {    //同步缓存        wx.setStorageSync(cacheKey, cacheInfo[propertyName])      } else {        //异步缓存        wx.setStorage({          key: cacheKey,          data: cacheInfo[propertyName],        })      }      if ("key_token" == cacheKey) {        getApp().globalData.token = cacheInfo[propertyName]      }    } catch (error) {      console.log("error===", error)    }  }  return true;}复制代码

6、Object对象的获取

export function getCacheValue(cacheKey, callback = null) {  if (!cacheKey) {    return null;  }  var realCacheKey = "key_" + cacheKey;  try {    if ((callback && typeof (callback) === "function")) {   //异步获取      wx.getStorage({        key: realCacheKey,        success: function (res) {          if ((callback && typeof (callback) === "function")) {            callback(res.data)          }        }      })    } else {    //同步获取      return wx.getStorageSync(realCacheKey)    }  } catch (error) {    console.log(error)  }}复制代码

转载于:https://juejin.im/post/5b9cd12e5188255c9031c21a

你可能感兴趣的文章
OSPF 配置
查看>>
退役总结
查看>>
【转】tomcat与apache,tomcat与servlet的区别
查看>>
mssql_exec少了对括号查了我老半天
查看>>
java笔记javaweb部分
查看>>
Cadence中画原理图的时候器件标号与黄色的参数不同的解决办法
查看>>
CMD-CMD命令之新建一个用户!
查看>>
软件测试基础--笔记3
查看>>
06-多表操作
查看>>
@Controller和@RestController的区别?
查看>>
MyBatis学习总结(三)——优化MyBatis配置文件中的配置
查看>>
Android上安装第三方库
查看>>
Dijkstra队列优化矩阵版
查看>>
Apache Nutch 1.3 学习笔记四(Generate)
查看>>
常用软件目录
查看>>
安装lxml时gcc: internal compiler error: Killed (program cc1)的解决方法
查看>>
Android长截屏-- ScrollView,ListView及RecyclerView截屏
查看>>
ChainMapper ,ChainReducer,多个Job串行
查看>>
Python hasattr() 函数
查看>>
JavaScript如何给Table行设置颜色?
查看>>