[探索] 利用promise做一个请求锁
在最近开发小程序的过程中,遇到一个需求,就是请求的时候header需要带上accessToken, accessToken是通过登陆接口返回的参数,可能会出现过期的情况,则需要重新登陆,所以每次加载小程序都会进行一次本地储存的accessToken校验,但是再小程序的运行机制下,app的onLaunch,加载pages的onLoad会并发执行,在弱网的情况下,并发可能导致accessToken还没校验完,page的请求函数就开始执行了,这样很容易会导致接口异常,本来的解决办法是在每个page页面调接口之前都await一下app.js里面checkAccessToken的方法,但是这样写起来不太友好
解决思路:
在request的基础上封装多一层锁,当accessToekn校验完成之前,其他进来的请求都进行等待,不进行请求,等待校验完成,才开始其他请求
原理分析
- 对原有的request请求做一次封装
- 利用promise的特性以及js对象存储在内存的特性, 配合async/await,让其他请求等待关键请求完成再开始请求,从而实现请求锁
- 首先等待关键请求完成了,再通过返回进入判断是否经过需要
代码分析
首先模拟一次请求
// 模拟一次请求发起
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的基础上加一层封装
- 参数设置两种,withOutLock用于某些不需要等待的请求直接跳过逻辑,lockOthers用于锁住在关键请求之后进来的请求
- 关键请求进来直接执行,
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做一个请求锁相关推荐
- 【Redis笔记】一起学习Redis | 如何利用Redis实现一个分布式锁?
一起学习Redis | 如何利用Redis实现一个分布式锁? 前提知识 什么是分布式锁? 为什么需要分布式锁? 分布式锁的5要素和三种实现方式 实现分布式锁 思考思考 基础方案 改进方案 保证setn ...
- 使用Golang利用ectd实现一个分布式锁
http://blog.codeg.cn/post/blog/2016-02-24-distrubute-lock-over-etcd/ By zieckey · 2016年02月24日 · 1205 ...
- python自己做个定时器_技术图文:如何利用 Python 做一个简单的定时器类?
原标题:技术图文:如何利用 Python 做一个简单的定时器类? 背景 今天在B站上看有关 Python 最火的一个教学视频 -- "零基础入门学习 Python",这也是我们 P ...
- 利用pgzero做一个接球的小游戏
利用pgzero做一个接球的小游戏 说明 pgzero为python的一个用于游戏制作的库,它基于pygame模块 可用如下命令去安装 pip install pygame pip install p ...
- 利用Python做一个简单的对战小游戏
利用Python做一个简单的文字对战小游戏 一.游戏介绍 1.大体介绍:文字版的对战小游戏,可以利用Python随机生成两个角色,角色带有各自的血量和攻击值两个指标.两人在对战时同时攻击对方,同时造成 ...
- 利用Python做一个漂亮小姐姐词云跳舞视频
最近不少小伙伴在学 Python,想找个好玩的练手项目. 那今天分享一个,简单,适合新手的 Python 小项目. 以下是具体项目: 本文将以哔哩哔哩–乘风破浪视频为例,you-get下载视频. 同时 ...
- 利用stm32做一个升级版的电子多功能密码锁
`自己利用空闲时间制作的电子密码锁,有PCB.原理图,PCB印制电路板.此设计用外部存储器,支持修改密码,本来想添加指纹识别模块,但是12864的数据口被使用了,gpio口不够用.在实际中我发现128 ...
- 小王,在 Java 中如何利用 redis 实现一个分布式锁服务呢???
作者:杨高超 juejin.im/post/5a4984af6fb9a0450b66bc57 在现代的编程语言中,接触过多线程编程的程序员多多少少对锁有一定的了解.简单的说,多线程中的锁就是在多线程环 ...
- 利用正则做一个会员注册管理系统
今天学习了利用正则来做一个会员注册管理系统,该系统的主要难点在于: 1.利用正则来判断账号以及密码是否合法 2.字典的增删查改 3.while循环,break,嵌套if判断语句 正则我是在 [正则网页 ...
最新文章
- OKR与Scrum如何强强联手
- 设备和驱动在第一次加载,会遍历总线
- Android启动过程深入解析【转】
- HDU 1175 连连看 dfs+剪枝
- poj 1995 Raising Modulo Numbers 二分快速幂
- python 矩阵库_NumPy 矩阵库(Matrix)
- linux-获取帮助-ls命令-date命令-man命令
- 线程的简单理解,适用于初接触的小白,另类例子讲解,通俗易懂
- 英语词根与说文解字词典读书笔记,并总结输出思维导图
- 脸大脖子短,适合什么发型?
- hibernate一对多关系
- 杨国福和张亮“天地对决” 麻辣烫江湖要变天了吗?
- 深度学习的过拟合与欠拟合问题的介绍与解决方案
- 020 怎样才可以把py文件前面的小箭头去掉
- android微信群聊功能,微信安卓内测更新,这个群聊功能等了8年
- 国家气象局提供的天气预报接口(完整Json接口)
- 服务器无法获取header请求头参数
- 开源至上:java前端框架排行
- SAP EPIC 银企直连 交易明细查询(建设银行)
- 如何查看键盘上面的键值?