使用Promise和localStorage对象实现本地缓存

这里写目录标题

  • 需求分析
  • 概念详解
  • 需求解析
  • 核心逻辑

需求分析

有时候我们从服务器请求到的部分数据在一定时间内是不会变化的,此时重复请求不仅浪费带宽,在网络状态波动时也会降低体验。所以我们希望把这部分数据缓存在本地,当手动清除或过期后再向服务器请求。

概念详解

Promise详解
localStorage详解
简单总结:

  • localStorage就是一个可以存储键值对的Map,key、value均限制为String类型,因此我们存储对象时需要用JSON.stringify将其转换为Json字符串,取出对象时需要用JSON.parse将字符串解析为Json对象。
  • Promise对象在构造时调用resolve方法可以向回调函数传递对象,而Promise对象使用 .then(res=>{})定义回调函数时,可以拿到resolve传递过来的对象;可以保证前面的耗时操作完成时再执行后续操作(阻塞)。
  • 我们可以发现axios也会有.then方法,所以其实它也是返回的一个Promise对象。

需求解析

localStorage的key为String类型,我们需要保证它的唯一性的同时,还要保证查询的时候能够找到。本例中我使用这样一个方法来生成key,可以直接把用于请求的参数对象传入作为key使用(注:有时字段传递数字只有数字的字符串时会得到相同的响应结果,但是使用此方法会生成不同的key):

let getCacheKey = function (prefix, json) {
    return prefix + " " + JSON.stringify(json);
}

由于localStorage对象并不自带过期功能,所以我们不仅需要存储数据,还要存储一个时间戳来验证它是否过期(同时需要给用户提供手动清除缓存的功能)。

本例中在数据key之后拼接一个"Expires"来作为时间戳的key。

核心逻辑

需要传入的参数:

  • key
  • 过期时长
  • 当缓存中没有数据时,执行获取数据的方法
  • 上述方法执行时所需要的参数(不定长)

操作流程:

  1. 尝试从localStorage中取出数据和时间戳,如果数据存在且在有效期内,直接返回该数据
  2. 如果数据不存在或者已过期,则执行获取数据的方法,在获得数据之后把数据存储到localStorage中、更新时间戳并返回该数据

注:我们发现获取数据的方法可能是耗时的,因此在定义该方法时需要返回一个Promise对象以调用它的回调函数来获取数据。例如:

let requestMethod = function(url,json){
	return new Promise(resolve => {
		axios.post(url, json).then(res=> {
			/*do something*/
			resolve(res)
		})
	}
}

核心方法:

let getData = function (key, expiresMinutes, requestMethod, ...param) {
    let expires = key + "Expires";
    let p = localStorage.getItem(key);
    let pe = localStorage.getItem(expires);
    let parse = JSON.parse(p);
    let now = new Date().getTime();
    console.log("key = " + key)
    console.log(parse)
    //当localStorage中有数据,且在有效期内时,直接返回当中的数据
    if (p !== null && now - pe < 1000 * 60 * expiresMinutes) {
        return new Promise(resolve => {
            resolve(parse);
        });
    }
    //当localStorage中无数据,或数据过期时,执行请求方法获取数据,并将获取到的数据存储到localStorage中
    return new Promise(resolve => {
        requestMethod(...param).then(res => {
            if (res === null) {
                alert("数据请求失败");
            }
            localStorage.setItem(key, JSON.stringify(res));
            localStorage.setItem(expires, JSON.stringify(now));
            resolve(res);
        });
    })
}

调用

getData(key, expiresMinutes, requestMethod, ...param).then(res=>{
	/*do something*/
})

你可能感兴趣的:(json,javascript)