js使用Promise实现简单的Ajax缓存


Posted in Javascript onNovember 14, 2018

业务场景

在不少业务场景下,我们需要实现简单的请求缓存(即某个请求只发起一次请求),例如上传 Token 的获取、获取配置的接口等。

这些接口可以通过 Promise 实现简单的缓存并能够控制更新,而不需要另外引入缓存层。

示范代码

用七牛上传作例子,一般我们会把七牛上传封装为一个单独的 Upload 组件,外部只需要调用组件,而 token 的获取封装到组件内部实现。

//Upload.vue
let fetchToken = null;
export default {
 data() {
  return {
   token: ''
  };
 },
 methods: {
  async upload() {
   try {
    // ...
   }
   catch(err) {
    alert(err.message);
    this.refreshToken();
   }
  },
  refreshToken() {
   fetchToken = null;
   this.fetchToken();
  },
  fetchToken() {
   if (!fetchToken) {
    fetchToken = request.get('/api/qiniu/token');
   }
   try {
    this.token = await fetchToken;
   }
   catch(err) {
    console.error(err);
   }
  }
 },
 created() {
  this.fetchToken();
 }
};

上面是一个简单的缓存上传 token 的例子,并且会在上传失败时刷新 token。

与直接缓存 Token 的值比较,缓存请求有什么好处?

// 缓存值的代码
export default {
 methods: {
  fetchToken() {
   if (!fetchToken) {
    fetchToken = await request.get('/api/qiniu/token');
   }
   try {
    this.token = fetchToken;
   }
   catch(err) {
    console.error(err);
   }
  }
 }
}

一个比较常见的 Upload 组件 的应用场景,在一个页面里同时使用多次该组件。

<template>
 <div class="upload1"><upload /></div>
 <div class="upload2"><upload /></div>
</template>

就上面的代码例子,如果使用缓存值的方法,那么页面一打开就会请求两次获取 Token 接口。

继续完善 Upload 组件

//Upload.vue
let fetchToken = null;
export default {
 methods: {
  async upload() {
   try {
    this.fetchToken();
    const token = await fetchToken;
    // ...
   } catch (err) {
    alert(err.message);
    this.refreshToken();
   }
  },
  refreshToken() {
   fetchToken = null;
   this.fetchToken();
  },
  fetchToken() {
   if (!fetchToken) {
    fetchToken = request.get('/api/qiniu/token');
   }
  }
 },
 created() {
  this.fetchToken();
 }
};

为了防止多个 Upload 组件 token 不同步问题,不再通过this.token保存 token,而是每次都等待 fetchToken resolved,保证获取到的 token 一定是最新的。

当然,这里还有很多需要优化,例如失败后的重试、判断是 401 失败才刷新 token、设置错误时间、定时刷新等等,但总体思路就是上面代码所展示的内容。

另外再介绍一个经典应用场景

const fetchConfig = (() => {
 let configRequest = null;
 return () => {
  if (!configRequest) {
   configRequest = Promise.all([services.customer.config1, services.customer.config2])
    .then(([data1, data2]) => {
     return { data1, data2 };
    })
    .catch(err => {
     configRequest = null;
     return Promise.reject(err);
    });
  }
  return configRequest;
 };
})();

export default {
 async beforeRouteEnter(to, from, next) {
  try {
   // 配置信息仅需要成功请求一次
   const [data, config] = await Promise.all([services.customer.getInfo(), fetchConfig()]);
   next(vm => {
    vm.data = data;
    vm.config = config;
    vm.init();
   };
  } catch (err) {
   next(err);
  }
 }
};

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript之锁定表格栏位
Jun 29 Javascript
JavaScript 定义function的三种方式小结
Oct 16 Javascript
js 数组的for循环到底应该怎么写?
May 31 Javascript
JS动态获取当前时间,并写到特定的区域
May 03 Javascript
javascript基于HTML5 canvas制作画箭头组件
Jun 25 Javascript
微信小程序 生命周期详解
Oct 12 Javascript
js遮罩效果制作弹出注册界面效果
Jan 25 Javascript
详解angularJs模块ui-router之状态嵌套和视图嵌套
Apr 28 Javascript
Angular实现的自定义模糊查询、排序及三角箭头标注功能示例
Dec 28 Javascript
Angular4学习教程之DOM属性绑定详解
Jan 04 Javascript
基于Vue实现可以拖拽的树形表格实例详解
Oct 18 Javascript
Vue和Flask通信的实现
May 19 Vue.js
微信jssdk逻辑在vue中的运用详解
Nov 14 #Javascript
Puppeteer 爬取动态生成的网页实战
Nov 14 #Javascript
React和Vue中监听变量变化的方法
Nov 14 #Javascript
详解jQuery获取特殊属性的值以及设置内容
Nov 14 #jQuery
浅谈vue中关于checkbox数据绑定v-model指令的个人理解
Nov 14 #Javascript
js html实现计算器功能
Nov 13 #Javascript
JavaScript使用类似break机制中断forEach循环的方法
Nov 13 #Javascript
You might like
php对包含html标签的字符串进行截取的函数分享
2014/06/19 PHP
thinkPHP中配置的读取与C方法详解
2016/12/05 PHP
jQuery入门问答 整理的几个常见的初学者问题
2010/02/22 Javascript
从零开始学习jQuery (八) 插播:jQuery实施方案
2011/02/23 Javascript
JS 按钮点击触发(兼容IE、火狐)
2013/08/07 Javascript
js如何判断不同系统的浏览器类型
2013/10/28 Javascript
html5+javascript制作简易画板附图
2014/04/25 Javascript
JavaScript数值数组排序示例分享
2014/05/27 Javascript
Node.js 的异步 IO 性能探讨
2014/10/08 Javascript
node.js中的fs.readlink方法使用说明
2014/12/17 Javascript
JavaScript中的冒泡排序法
2016/08/03 Javascript
JS简单获取当前日期时间的方法(如:2017-03-29 11:41:10 星期四)
2017/03/29 Javascript
react native带索引的城市列表组件的实例代码
2017/08/08 Javascript
简单的Vue异步组件实例Demo
2017/12/27 Javascript
vue.js根据代码运行环境选择baseurl的方法
2018/02/28 Javascript
vue实例中data使用return包裹的方法
2018/08/27 Javascript
layui的表单验证支持ajax判断用户名是否重复的实例
2019/09/06 Javascript
Python中with及contextlib的用法详解
2017/06/08 Python
Python3中的列表,元组,字典,字符串相关知识小结
2017/11/10 Python
详解Python中的Numpy、SciPy、MatPlotLib安装与配置
2017/11/17 Python
Python定时任务APScheduler的实例实例详解
2019/07/22 Python
Pytorch Tensor的索引与切片例子
2019/08/18 Python
python同步windows和linux文件
2019/08/29 Python
Python numpy线性代数用法实例解析
2019/11/15 Python
Flask中sqlalchemy模块的实例用法
2020/08/02 Python
Python基于Webhook实现github自动化部署
2020/11/28 Python
Becextech新西兰:数码单反相机和手机在线商店
2018/04/27 全球购物
捷克家电和家具购物网站:OKAY.cz
2020/07/23 全球购物
研发工程师的岗位职责
2013/11/18 职场文书
土木建筑学生自我评价
2014/01/14 职场文书
电话客服专员岗位职责
2014/06/28 职场文书
酒会邀请函
2015/01/31 职场文书
护士医德医风心得体会
2016/01/25 职场文书
PHP实现创建以太坊钱包转账等功能
2021/04/21 PHP
写一个Python脚本下载哔哩哔哩舞蹈区的所有视频
2021/05/31 Python
在HTML中引入CSS的几种方式介绍
2021/12/06 HTML / CSS