unicloud云开发进阶29-项目13将数据进行缓存setStorageSync提供性能

60 阅读4分钟

对请求进行限制

如果频繁请求,IP可能会被封,所以一旦请求成功就先把结果放到缓存中,再次请求时就先查看缓存中有没有城市,有就用这个结果,没有才请求

做这个功能之前,先做一个判断是否拿到了值的功能,如果有值,返回值就是字符串,如果没有值,接口的返回值是一个空数组

// 高德API
export function getProvince() {
  // resolve是成功的返回值,reject是异常的返回值
  return new Promise((resolve, reject) => {
    uni.request({
      url: "https://restapi.amap.com/v3/ip?key=39ed194180a6414d9650bbdfe6386814",
      success: res => {
        // 使用resolve返回结果
        // 如果是空值,返回值是一个空数组
        if(typeof(res.data.province)=="string"){
          resolve(res.data.province);
        }else{
          resolve("火星")
        }
      },
      fail:err=>{
        reject(err)
      }
    })
  })
}

接下来做缓存功能

// 高德API
export function getProvince() {
  // resolve是成功的返回值,reject是异常的返回值
  return new Promise((resolve, reject) => {
    uni.request({
      url: "https://restapi.amap.com/v3/ip?key=39ed194180a6414d9650bbdfe6386814",
      success: res => {
        let str = ""
        // 使用resolve返回结果
        // 如果是空值,返回值是一个空数组
        // if(typeof(res.data.province)=="string"){
        //   str=res.data.province;
        // }else{
        //   str="火星"
        // }
        // 上面写法和下面一样,三元表达式更清晰
        typeof(res.data.province)=="string" ? str=res.data.province : str="火星"
        resolve(str)
        let obj={
          province:str,
          time:Date.now()
        }
        // 将结果保存到缓存中
        uni.setStorageSync("ahistoryProvince",obj);
      },
      fail:err=>{
        reject(err)
      }
    })
  })
}

省份和时间戳都存进来了 image.png

然后是判断缓存中是否有存在信息,有就直接返回

// 高德API
export function getProvince() {
  // resolve是成功的返回值,reject是异常的返回值
  return new Promise((resolve, reject) => {
    let historyProvince = uni.getStorageSync("historyProvince");

    // 判断缓存中是否有省份信息
    if (historyProvince) {
      // 有接直接返回结果
      resolve(historyProvince.province)
    } else {
      // 缓存中没有值才走下面代码
      uni.request({
        url: "https://restapi.amap.com/v3/ip?key=39ed194180a6414d9650bbdfe6386814",
        success: res => {
          let str = ""
          // 使用resolve返回结果
          // 如果是空值,返回值是一个空数组
          // if(typeof(res.data.province)=="string"){
          //   str=res.data.province;
          // }else{
          //   str="火星"
          // }
          // 上面写法和下面一样,三元表达式更清晰
          typeof(res.data.province) == "string" ? str = res.data.province: str = "火星"
          resolve(str)
          let obj = {
            province: str,
            time: Date.now()
          }
          // 将结果保存到缓存中
          uni.setStorageSync("historyProvince", obj);
        },
        fail: err => {
          reject(err)
        }
      })
    }
  })
}

封装高德网络请求库

上面存储了一个时间戳没用上,是为了和当前执行这个方法的时间戳进行对比,如果超过一小时,或者超过一天,就重新进行一次网络请求,这样对获取网络归属地进行更新,具体时间自行设置,这里一小时一次更新

先重构,把获取网络请求的代码和逻辑判断的代码分离成两个函数

// 高德API
export function getProvince() {
  // resolve是成功的返回值,reject是异常的返回值
  return new Promise((resolve, reject) => {
    let historyProvince = uni.getStorageSync("historyProvince");

    // 判断缓存中是否有省份信息
    if (historyProvince) {
      // 有接直接返回结果
      resolve(historyProvince.province)
    } else {
      // then里面的res才是getIp方法中resolve返回的值
      getIp().then(res=>{
        // 这个resolve是属于当前这个方法的,res里的是下面getip方法的resolve
        resolve(res)
      }).catch(err=>{
        reject(err)
      })
    }
  })
}

// 把网络请求独立出来,写成一个promiose对象
// 这里前面不加function会报错
function getIp(){
  return new Promise((resolve,reject)=>{
    // 缓存中没有值才走下面代码
    uni.request({
      url: "https://restapi.amap.com/v3/ip?key=39ed194180a6414d9650bbdfe6386814",
      success: res => {
        let str = ""
        // 使用resolve返回结果
        // 如果是空值,返回值是一个空数组
        // if(typeof(res.data.province)=="string"){
        //   str=res.data.province;
        // }else{
        //   str="火星"
        // }
        // 上面写法和下面一样,三元表达式更清晰
        typeof(res.data.province) == "string" ? str = res.data.province: str = "火星"
        resolve(str)
        let obj = {
          province: str,
          time: Date.now()
        }
        // 将结果保存到缓存中
        uni.setStorageSync("historyProvince", obj);
      },
      fail: err => {
        reject(err)
      }
    })
  })
}

下面是对时间戳进行判断

// 向外导出
// 高德API
export function getProvince() {
  // resolve是成功的返回值,reject是异常的返回值
  return new Promise((resolve, reject) => {
    let historyProvince = uni.getStorageSync("historyProvince");

    // 判断缓存中是否有省份信息
    if (historyProvince) {
      // 判断当前时间戳减去缓存中的时间戳差值超过1小时就重新发起网络请求
      if((Date.now() - historyProvince.tiem) > 1000*60*60){
        // 重新发起网络请求
        // then里面的res才是getIp方法中resolve返回的值
        getIp().then(res=>{
          // 这个resolve是属于当前这个方法的,res里的是下面getip方法的resolve
          resolve(res)
        }).catch(err=>{
          reject(err)
        })
      }else{
        // 如果在一小时内,直接提取缓存中保存的数据
        // 有接直接返回结果
        resolve(historyProvince.province)
      }
    } else {
      // 如果缓存中没有记录,就发起网络请求获取归属地
      // then里面的res才是getIp方法中resolve返回的值
      getIp().then(res=>{
        // 这个resolve是属于当前这个方法的,res里的是下面getip方法的resolve
        resolve(res)
      }).catch(err=>{
        reject(err)
      })
    }
  })
}

// 获取省市信息
// 把网络请求独立出来,写成一个promiose对象
// 这里前面不加function会报错
function getIp(){
  return new Promise((resolve,reject)=>{
    // 缓存中没有值才走下面代码
    uni.request({
      url: "https://restapi.amap.com/v3/ip?key=39ed194180a6414d9650bbdfe6386814",
      success: res => {
        let str = ""
        // 使用resolve返回结果
        // 如果是空值,返回值是一个空数组
        // if(typeof(res.data.province)=="string"){
        //   str=res.data.province;
        // }else{
        //   str="火星"
        // }
        // 上面写法和下面一样,三元表达式更清晰
        typeof(res.data.province) == "string" ? str = res.data.province: str = "火星"
        resolve(str)
        let obj = {
          province: str,
          time: Date.now()
        }
        // 将结果保存到缓存中
        uni.setStorageSync("historyProvince", obj);
      },
      fail: err => {
        reject(err)
      }
    })
  })
}