vue基于WebSql实现的仿redis前端缓存,前端实现请求接口数据缓存

4 篇文章 0 订阅
3 篇文章 0 订阅

使用场景

防止用户过渡刷新或切换界面,不断的请求后端接口,所以在前端对用户拿到的部分数据进行缓存。

特别是查看分页数据的情况,用户频繁切换界面是可以有效的对数据进行缓存。

目录结构

WebSql.js 创建数据库表,储存key,value,过期时间

import Vue from 'vue'
import {executeSql} from '@/utils/localDb'

const WebSql=function(){
  if(window.openDatabase){
    var db = openDatabase('xb','1.0','xiaobao',200*1024*1024);
    Vue.prototype.$db=db;
    if(!db){
      console.log("本地数据库创建失败");
    }else{
      executeSql('CREATE TABLE IF NOT EXISTS local_cache (key,value,time)');
      console.log('本地数据库创建成功');
    }
  }else{
    console.log('不支持本地存储');
  }
};
export default WebSql;

localDb.js

import Vue from 'vue'

export   function executeSql (sqlStatement, arg, callback, errorCallback) {
 Vue.prototype.$db.transaction(function (tx) {
    tx.executeSql(sqlStatement, arg, callback, errorCallback);
  });
}
export  function insert (key,value,time) {
  value=JSON.stringify(value);
  executeSql('INSERT INTO local_cache (key,value,time) VALUES (?,?,?)',[key,value,time])
}
export  function deletebykey(key) {
  executeSql('delete from local_cache where key = ?',[key])
}
export  function deletebytime() {
  executeSql('delete from local_cache where time > 0 and time < '+gettime())
}
//设置值的值和过期时间
export  function setcache (key,value,time) {
  if(time!==0){
      deletebykey(key);
      insert(key,value,time>0?1000*time+gettime():-1)
  }
  deletebytime();
}
//获取key的值
export  function getcache (key,value) {
  deletebytime();
  var returnstr;
   Vue.prototype.$db.transaction( function (tx) {
     tx.executeSql('SELECT * FROM local_cache where key = ?', [key], function (tx, results) {
      var len = results.rows.length, i;
      if (len && len > 0) {
        returnstr=JSON.parse(results.rows.item(0).value);
      }
      value(returnstr);
    },  a=>{
       value(returnstr)
     });
  });
}
//刷新key的有效期
export function expire (key,time) {
  executeSql('update local_cache set time = ? where key = ? ',[1000*time+gettime(),key])
}
export  function gettime () {
  return new Date().getTime();
}

main.js新增

import WebSql from '@/utils/WebSql'

Vue.use(WebSql)

========================================上面的代码可以基本实现缓存====================================

request.js
请求工具类,这个工具是来源于ruoyi-vue,大家需要根据自己的项目再修改一下。

import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 超时
  timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
  // 是否需要设置 token
  const isToken = (config.headers || {}).isToken === false
  if (getToken() && !isToken) {
    config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
  }
  // get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?';
    for (const propName of Object.keys(config.params)) {
      const value = config.params[propName];
      var part = encodeURIComponent(propName) + "=";
      if (value && typeof(value) !== "undefined") {
        if (typeof value === 'object') {
          for (const key of Object.keys(value)) {
            let params = propName + '[' + key + ']';
            var subPart = encodeURIComponent(params) + "=";
            url += subPart + encodeURIComponent(value[key]) + "&";
          }
        } else {
          url += part + encodeURIComponent(value) + "&";
        }
      }
    }
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }
  return config
}, error => {
    console.log(error)
    Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
    // 未设置状态码则默认成功状态
    const code = res.data.code || 200;
    // 获取错误信息
    const msg = errorCode[code] || res.data.msg || errorCode['default']
    if (code === 401) {
      MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
          confirmButtonText: '重新登录',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(() => {
       /* store.dispatch('LogOut').then(() => {
          location.href = '/index';
        })*/
      })
    } else if (code === 500) {
      Message({
        message: msg,
        type: 'error'
      })
      return Promise.reject(new Error(msg))
    } else if (code !== 200) {
      Notification.error({
        title: msg
      })
      return Promise.reject('error')
    } else {
      return res.data
    }
  },
  error => {
    console.log('err' + error)
    let { message } = error;
    if (message == "Network Error") {
      message = "后端接口连接异常";
    }
    else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    }
    else if (message.includes("Request failed with status code")) {
      message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    Message({
      message: message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service

带有缓存的request工具类

cacheRequest.js

import request from '@/utils/request'
import {getcache, setcache} from '@/utils/localDb'

export function cacheRequest (url,method,data,time) {

  if(time!==0){
    var key=JSON.stringify({url:url,method:method,data:data});
    return  new Promise(function(resolve, reject) {
      getcache(key,(value)=>{
        console.log(value)
        if(value){
          resolve(value)
        }else{
          request({
            url: url,
            method: method,
            data: data
          }).then(a=>{
            setcache(key,a,time);
            resolve(a)
          })
        }
      })
    });
  }else{
     return request({
      url: url,
      method: method,
      data: data
    })

  }
}

==============到这里就可以了=================

后面这些是大家如果可以用上的话,也可以拷贝到自己项目,来源于ruoyi-vue

errorCode.js

export default {
  '401': '认证失败,无法访问系统资源',
  '403': '当前操作没有权限',
  '404': '访问资源不存在',
  'default': '系统未知错误,请反馈给管理员'
}

auth.js

import Cookies from 'js-cookie'

const TokenKey = 'Admin-Token'

export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token) {
  return Cookies.set(TokenKey, token)
}

export function removeToken() {
  return Cookies.remove(TokenKey)
}

===============以下是我用于测试界面,拷贝到自己项目后添加到自己路由里即可================

项目需要引入element-ui,或者自己修改一下。

<template>
    <div>
      <div>
        {{returnstr}}
      </div>
      <el-input v-model="key">key</el-input>
      <el-input v-model="value">value</el-input>
      <el-input v-model="time">time</el-input>
      <el-input v-model="method">method</el-input>
      <el-button @click="add()">
        新增
      </el-button>
      <el-button @click="get()">
        查询
      </el-button>
      <el-button @click="ajaxtest()">
        ajax
      </el-button>
    </div>
</template>

<script>

  import {getcache, setcache} from '@/utils/localDb'
  import {cacheRequest} from '@/utils/cacheRequest'
  export default {
    name: 'test.vue',
    data( ) {
      return{
        key:'http://localhost/dev-api/captchaImage',//你的后端接口 或者存缓存的key
        value:'1234',//接口参数或者存缓存的value
        time:10,//缓存过期时间 为0则不缓存,小于0则不过期。
        returnstr:'这里是显示返回的结果',
        method:'GET',
      }
    },
    methods:{
      add(){
        setcache(this.key,this.value,this.time)
      },
      get(){
        this.returnstr=getcache(this.key, (value)=> {
          this.returnstr=value;
        });
      },
      ajaxtest(){
        cacheRequest(this.key,this.method,this.value,this.time)
          .then(a=>{
            this.returnstr=a;
          })
      }

    }
  }
</script>

<style scoped>



</style>

写的相对不是那么的规范,仅供大家参考。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值