在最近开发小程序的过程中,遇到一个需求,就是请求的时候header需要带上accessToken, accessToken是通过登陆接口返回的参数,可能会出现过期的情况,则需要重新登陆,所以每次加载小程序都会进行一次本地储存的accessToken校验,但是再小程序的运行机制下,app的onLaunch,加载pages的onLoad会并发执行,在弱网的情况下,并发可能导致accessToken还没校验完,page的请求函数就开始执行了,这样很容易会导致接口异常,本来的解决办法是在每个page页面调接口之前都await一下app.js里面checkAccessToken的方法,但是这样写起来不太友好

解决思路:

在request的基础上封装多一层锁,当accessToekn校验完成之前,其他进来的请求都进行等待,不进行请求,等待校验完成,才开始其他请求

原理分析

  1. 对原有的request请求做一次封装
  2. 利用promise的特性以及js对象存储在内存的特性, 配合async/await,让其他请求等待关键请求完成再开始请求,从而实现请求锁
  3. 首先等待关键请求完成了,再通过返回进入判断是否经过需要

代码分析

首先模拟一次请求

// 模拟一次请求发起
const mockRequest = (name, time = Math.random() * 1000) =>new Promise(reslove => {console.log(`${name}---------------run`);setTimeout(() => {reslove(`${name}---------------done`);}, time);});

定义请求锁

请求锁要管理两种状态,一种是关键请求进行是状态,一种是当关键请求失败了之后,需要等待辅助操作完成的状态

const lock = { wait: null, runing: null };

在request的基础上加一层封装

  1. 参数设置两种,withOutLock用于某些不需要等待的请求直接跳过逻辑,lockOthers用于锁住在关键请求之后进来的请求
  2. 关键请求进来直接执行,
    lock.runing

    直接赋予关键请求的pending状态,当其他请求进来的时候,都直接等待,不进行请求发起,等主要请求进来完成之后,其他才开始执行


// 封装模拟request
const request = async (name,opts = { withOutLock: false, lockOthers: false, hasErr: false }
) => {// 不需要等待的请求直接执行if (opts.withOutLock) {const res = await mockRequest(`${name} - withOutLock`);console.log(res);return;}// 关键请求未执行完成 其他请求进入等待状态if (lock.runing) {console.log(`${name}---------------wating...`);await lock.runing;}// 锁住之后进来的请求if (opts.lockOthers) {lock.runing = mockRequest(name, 4000);let res = await lock.runing;// 清空进行锁lock.runing = null;// 模拟关键请求失败的 需要再次等待其他操作的情况 例如重新登陆等if (opts.hasErr) {lock.wait = mockRequest("关键请求异常处理", 4000);} else {console.log(res);return;}}// 等待模拟关键请求失败的处理if (lock.wait) {console.log(`等待关键请求异常处理中...`);await lock.wait;// 清空等待锁lock.wait = null;console.log(`关键请求异常处理完成`);}const res = await mockRequest(name);console.log(res);return;
};

模拟运行效果


// 并发请求模拟
const mockConcurrent = () => {for (let i = 0; i < 5; i  ) {setTimeout(() => {request(`并发请求${i}`, { withOutLock: i === 0 });}, Math.random() * 100);}
};request("关键请求 - 其他需要等待完成才能进行", {lockOthers: true,hasErr: false
});mockConcurrent();

运行时效果


最后

经过同事的指点,未来还打算探究一下请求池,做请求上下文之类的实现

demo代码: 具体例子代码demo参考

纯技术探索,坑点未知,欢迎指出错误以及不足的地方

[探索] 利用promise做一个请求锁相关推荐

  1. 【Redis笔记】一起学习Redis | 如何利用Redis实现一个分布式锁?

    一起学习Redis | 如何利用Redis实现一个分布式锁? 前提知识 什么是分布式锁? 为什么需要分布式锁? 分布式锁的5要素和三种实现方式 实现分布式锁 思考思考 基础方案 改进方案 保证setn ...

  2. 使用Golang利用ectd实现一个分布式锁

    http://blog.codeg.cn/post/blog/2016-02-24-distrubute-lock-over-etcd/ By zieckey · 2016年02月24日 · 1205 ...

  3. python自己做个定时器_技术图文:如何利用 Python 做一个简单的定时器类?

    原标题:技术图文:如何利用 Python 做一个简单的定时器类? 背景 今天在B站上看有关 Python 最火的一个教学视频 -- "零基础入门学习 Python",这也是我们 P ...

  4. 利用pgzero做一个接球的小游戏

    利用pgzero做一个接球的小游戏 说明 pgzero为python的一个用于游戏制作的库,它基于pygame模块 可用如下命令去安装 pip install pygame pip install p ...

  5. 利用Python做一个简单的对战小游戏

    利用Python做一个简单的文字对战小游戏 一.游戏介绍 1.大体介绍:文字版的对战小游戏,可以利用Python随机生成两个角色,角色带有各自的血量和攻击值两个指标.两人在对战时同时攻击对方,同时造成 ...

  6. 利用Python做一个漂亮小姐姐词云跳舞视频

    最近不少小伙伴在学 Python,想找个好玩的练手项目. 那今天分享一个,简单,适合新手的 Python 小项目. 以下是具体项目: 本文将以哔哩哔哩–乘风破浪视频为例,you-get下载视频. 同时 ...

  7. 利用stm32做一个升级版的电子多功能密码锁

    `自己利用空闲时间制作的电子密码锁,有PCB.原理图,PCB印制电路板.此设计用外部存储器,支持修改密码,本来想添加指纹识别模块,但是12864的数据口被使用了,gpio口不够用.在实际中我发现128 ...

  8. 小王,在 Java 中如何利用 redis 实现一个分布式锁服务呢???

    作者:杨高超 juejin.im/post/5a4984af6fb9a0450b66bc57 在现代的编程语言中,接触过多线程编程的程序员多多少少对锁有一定的了解.简单的说,多线程中的锁就是在多线程环 ...

  9. 利用正则做一个会员注册管理系统

    今天学习了利用正则来做一个会员注册管理系统,该系统的主要难点在于: 1.利用正则来判断账号以及密码是否合法 2.字典的增删查改 3.while循环,break,嵌套if判断语句 正则我是在 [正则网页 ...

最新文章

  1. OKR与Scrum如何强强联手
  2. 设备和驱动在第一次加载,会遍历总线
  3. Android启动过程深入解析【转】
  4. HDU 1175 连连看 dfs+剪枝
  5. poj 1995 Raising Modulo Numbers 二分快速幂
  6. python 矩阵库_NumPy 矩阵库(Matrix)
  7. linux-获取帮助-ls命令-date命令-man命令
  8. 线程的简单理解,适用于初接触的小白,另类例子讲解,通俗易懂
  9. 英语词根与说文解字词典读书笔记,并总结输出思维导图
  10. 脸大脖子短,适合什么发型?
  11. hibernate一对多关系
  12. 杨国福和张亮“天地对决” 麻辣烫江湖要变天了吗?
  13. 深度学习的过拟合与欠拟合问题的介绍与解决方案
  14. 020 怎样才可以把py文件前面的小箭头去掉
  15. android微信群聊功能,微信安卓内测更新,这个群聊功能等了8年
  16. 国家气象局提供的天气预报接口(完整Json接口)
  17. 服务器无法获取header请求头参数
  18. 开源至上:java前端框架排行
  19. SAP EPIC 银企直连 交易明细查询(建设银行)
  20. 如何查看键盘上面的键值?

热门文章

  1. javabean 连接mysql_连接mysql的javabean实例+简单分页
  2. 持久化技术SharedPreferences存储
  3. uniapp 子组件 props拿不到数据_来吧!一文彻底搞定Vue组件!
  4. Java Web Token - JWT
  5. 使用Eclipse 创建 搭建SpringBoot项目
  6. iOS 11 UICollectionView顶部出现白色间隔的问题
  7. ubantu 中配置Flash Player
  8. 串口 驱动 热敏打印机_热敏纸标签打印不出来文字 是因为……
  9. matlab gradient
  10. 标准模板库STL学习总结