JS 中请求队列与锁的巧妙结合
一、引言
在 JavaScript 开发中,尤其是在涉及到异步操作和对共享资源的并发访问时,有效地控制请求顺序和资源访问权限至关重要。例如,在多个网络请求同时针对一个有限制访问频率的 API 或者多个异步任务竞争同一个文件写入权限的场景下,若不加以妥善处理,可能会导致数据混乱、请求失败或资源冲突等问题。本文将深入探讨如何在 JavaScript 中创建一个请求队列,当锁被占用时,将请求妥善地放入队列中,待锁释放后,再依次处理队列中的请求,从而确保系统的稳定性和正确性。
二、JS 中的异步锁实现
(一)简易异步锁对象
-
构造函数
- 首先,创建一个名为
AsyncLock
的函数构造器,用于生成异步锁对象实例。在构造函数内部,初始化以下几个重要属性:this.queue
:这是一个数组,用于存储被阻塞的请求任务。初始时,它被设置为空数组,因为还没有任何请求被阻塞。this.isLocked
:这是一个布尔值,用于表示锁的当前状态。初始化为false
,意味着锁是空闲的,资源可供使用。this.version
:这是一个字符串类型的属性,用于记录锁的版本信息。初始版本设置为'0'
,每当锁状态发生改变(如被获取或释放)时,版本号可以相应更新,这有助于在复杂的应用场景中跟踪锁的使用历史和状态变化。
- 以下是构造函数的代码示例:
- 首先,创建一个名为
function AsyncLock() {this.queue = [];this.isLocked = false;this.version = '0';
}
-
获取锁方法 -
lock
- 该方法用于尝试获取锁。如果当前锁已经被其他任务占用(即
this.isLocked === true
),则需要将当前请求任务加入到等待队列this.queue
中。 - 为了实现等待队列的功能,使用
await new Promise(resolve => this.queue.push(resolve));
。这里创建了一个新的Promise
,并将其resolve
函数添加到队列中。当锁被释放时,会从队列中取出这个resolve
函数并执行,从而继续执行被阻塞的任务。 - 如果等待队列的长度已经达到了某个设定的上限(例如 10),则表示系统可能存在资源紧张或者请求过多的情况,此时直接返回
false
,表示获取锁失败,避免队列无限增长导致内存溢出等问题。 - 如果成功获取锁(即锁原本是空闲的),则将
this.isLocked
设置为true
,并生成一个新的锁版本号(可以使用Date.now().toString()
等方式生成一个基于时间戳的唯一字符串作为版本号)。同时,为了防止锁被无限期占用,设置一个超时机制。如果在获取锁时没有传入特定的超时时间参数,则默认在 300 毫秒后自动释放锁。可以使用setTimeout
函数来实现超时释放锁的功能,在超时回调函数中调用this.unlock()
方法释放锁。 - 以下是
lock
方法的完整代码示例:
- 该方法用于尝试获取锁。如果当前锁已经被其他任务占用(即
AsyncLock.prototype.lock = async function (timeout = 300) {if (this.isLocked) {if (this.queue.length < 10) {await new Promise(resolve => this.queue.push(resolve));} else {return false;}}this.isLocked = true;this.version = Date.now().toString();const timer = setTimeout(() => {this.unlock();}, timeout);return true;
};
-
释放锁方法 -
unlock
- 该方法用于释放当前持有的锁。如果等待队列
this.queue
中有等待的任务(即this.queue.length > 0
),则从队列中取出第一个任务的resolve
函数并执行,这将唤醒被阻塞的任务,使其继续执行后续操作。通过const resolve = this.queue.shift(); resolve();
实现从队列头部取出并执行resolve
函数。 - 如果等待队列为空,说明没有任务在等待锁,此时将
this.isLocked
设置为false
,表示锁已经被释放,可以被其他任务获取。 - 以下是
unlock
方法的代码示例:
- 该方法用于释放当前持有的锁。如果等待队列
AsyncLock.prototype.unlock = function () {if (this.queue.length > 0) {const resolve = this.queue.shift();resolve();} else {this.isLocked = false;}
};
-
包装锁的获取与释放方法 -
withLock
- 为了更方便地在外部使用锁机制,创建一个
withLock
方法。这个方法是一个async
函数,它内部首先调用this.lock
方法尝试获取锁。如果获取锁成功(返回true
),则执行传入的任务函数(假设为task
),并在任务完成后调用this.unlock
方法释放锁。如果获取锁失败(返回false
),则直接返回一个表示locked
状态的对象或值,以便外部代码进行相应的处理。 - 以下是
withLock
方法的代码示例:
- 为了更方便地在外部使用锁机制,创建一个
AsyncLock.prototype.withLock = async function (task) {const locked = await this.lock();if (locked) {try {return await task();} finally {this.unlock();}} else {return { locked: true };}
};
三、使用示例
1、创建AsyncLock
的实例:
const asyncLock = new AsyncLock();
2、 定义一个异步函数test
来模拟请求任务:
async function test() {const result = await asyncLock.withLock(async () => {console.log('执行任务');// 这里可以添加具体的任务逻辑,例如网络请求、文件操作等return '任务完成';});if (result.locked) {console.log('获取锁失败');} else {console.log(result);}
}
3、 多次调用test
函数来测试锁机制:
test();
test();
test();
在上述示例中,当第一个test
函数调用时,如果锁空闲,它将获取锁并执行任务,打印 “执行任务”,然后释放锁。当第二个和第三个test
函数调用时,如果第一个test
函数还未释放锁,它们将被加入等待队列。一旦锁被释放,等待队列中的任务将依次被执行,从而实现了请求队列与锁机制的协同工作。
四、总结
在 JavaScript 中,通过精心设计和实现请求队列与异步锁的结合,可以有效地应对并发访问共享资源时可能出现的各种问题。这种机制不仅能够确保资源在同一时间只有一个任务能够访问,避免了数据竞争和冲突,而且通过合理的等待队列管理,能够有条不紊地处理多个请求,提高了系统的整体稳定性和可靠性。在实际的大型 JavaScript 应用开发中,尤其是涉及到复杂的异步操作和资源管理场景时,深入理解和熟练运用这种请求队列与锁的技术是非常必要的,可以帮助我们构建出更加健壮和高效的应用程序。
相关文章:
JS 中请求队列与锁的巧妙结合
一、引言 在 JavaScript 开发中,尤其是在涉及到异步操作和对共享资源的并发访问时,有效地控制请求顺序和资源访问权限至关重要。例如,在多个网络请求同时针对一个有限制访问频率的 API 或者多个异步任务竞争同一个文件写入权限的场景下&#…...
注意力机制+时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测
注意力机制时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测 目录 注意力机制时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测效果一览基本介绍程序设计参考资料 效果一览 基…...
Prefix Decoder /Causal Decoder/Encoder-Decoder的区别
Prefix Decoder 定义:Prefix Decoder,也称为非因果解码器,属于Decoder only结构。输入部分使用双向注意力,输出部分使用单向注意力。在生成新的输出时,会考虑到所有之前生成的输出。 特点:Prefix Decoder在…...
《智能体开发实战(高阶)》四、系统化的日志周报智能体开发计划
智能体扩展与完善规划 为了将前几个章节的智能体逐步扩展为支持整个公司团队使用的高效工具,以下是分阶段的完善与扩写规划。每个阶段旨在提升功能覆盖范围、处理能力和用户体验,并为企业提供实际价值。 阶段一:基础功能完善 目标:巩固现有功能,提升健壮性和适用性。 支…...
多线程编程杂谈(上)
问题 线程执行的过程中可以强制退出吗? 主动退出?被动退出? 问题抽象示例 需要解决的问题 g_run 全局变量需要保护吗? 如何编码使得线程中每行代码的执行可被 g_run 控制? 线程代码在被 g_run 控制并 "强制退…...
二五(Vue2-01)、创建实例、插值表达式、响应式、Vue指令、
1. Vue 概念及创建实例 <body><!-- 创建Vue实例,初始化渲染1. 准备容器 (Vue所管理的范围)2. 引包 (开发版本包 / 生产版本包) 官网3. 创建实例4. 添加配置项 > 完成渲染 --><div id"app"><h1>{{msg}}</h1><a href&…...
P8772 求和 P8716 回文日期
文章目录 [蓝桥杯 2022 省 A] 求和[蓝桥杯 2020 省 AB2] 回文日期 [蓝桥杯 2022 省 A] 求和 题目描述 给定 n n n 个整数 a 1 , a 2 , ⋯ , a n a_{1}, a_{2}, \cdots, a_{n} a1,a2,⋯,an, 求它们两两相乘再相加的和,即 S a 1 ⋅ a 2 a 1 ⋅ a 3 ⋯ a…...
Burp Suite(2)2024.1.1Burp Suite专业版激活(保姆级教程)
声明: 本文所使用的专业版BP在我的博客资源里面,需要的师傅可以自行下载。 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内…...
基于注意力的几何感知的深度学习对接模型 GAABind - 评测
GAABind 作者是苏州大学的生物基础与医学院, 期刊是 Briefings in Bioinformatics, 2024, 25(1), 1–14。GAABind 是一个基于注意力的几何感知蛋白-小分子结合模式与亲和力预测模型,可以捕捉小分子和蛋白的几何、拓扑结构特征以及相互作用。使用 PDBBind2020 和 CASF2016 作…...
Python中的优化函数2:cvxpy包
文章目录 介绍使用步骤示例1示例2官方文档 介绍 它是一个基于 Python 的凸优化建模工具,专门用于定义和求解 凸优化问题(Convex Optimization Problems)。CVXPY 提供了一种直观的方式来表达优化问题,并通过高效的求解器来解决这些…...
【Linux】结构化命令
结构化命令structured command:允许脚本根据条件跳过部分命令,改变执行流程。 1、if-then语句 格式1: if command then commands fi 格式2: if command; then commands fi 运行if之后的command命令,如果它的退出状态码…...
3-机器人视觉-机器人抓取与操作
文章目录 3机器人视觉目录 1. 传感器和标定摄像头模型Intrinsic MatrixExtrinsic Matrix 标定内参标定手眼标定和外参标定 力传感器&其它传感器其它传感器 2. 神经网络和图像处理2D特征处理常见架构 训练流程推理流程部署流程2D 图像任务3D Point Cloud FeaturePointNet Ap…...
LINUX——shell编程
Shell 简介 Shell 是一个 C 语言编写的脚本语言,它是用户与 Linux 的桥梁,用户输入命令交给 Shell 处理, Shell 将相应的操作传递给内核(Kernel),内核把处理的结果输出给用户。 下面是流程示意图ÿ…...
12.11函数 结构体 多文件编译
1.脑图 定义一个数组,用来存放从终端输入的5个学生的信息【学生的信息包含学生的姓名、年纪、性别、成绩】 1>封装函数 录入5个学生信息 2>封装函数 显示学生信息 3>封装函数 删除第几个学生信息,删除后调用显示学生信息函数 显示 4> 封…...
【go语言】reflect包与类型推断
reflect 包的核心概念 Go 中的反射涉及两个核心概念: Type:表示一个类型的结构体,reflect.Type 是类型的描述。Value:表示一个值的结构体,reflect.Value 是一个具体值的包装。 反射让我们能够动态地访问对象的类型和…...
docker启动一个helloworld(公司内网服务器)
这里写目录标题 容易遇到的问题:1、docker连接问题 我来介绍几种启动 Docker Hello World 的方法: 最简单的方式: docker run hello-world这会自动下载并运行官方的 hello-world 镜像。 使用 Nginx 作为 Hello World: docker…...
【瑞萨RA0E1开发板评测报告】IIC OLED 测试
【瑞萨RA0E1开发板评测报告】IIC OLED 测试 基于前面关于瑞萨 e studio 开发软件的使用,以及工程测试基础,本文进一步探索实现硬件 IIC OLED 的文字和图片显示。 1 背景 简单介绍 IIC 通信协议、OLED 显示原理、SS1306 驱动 IC 等。 IIC 通信协议 I…...
全球叉车市场 2023 - 2032 年发展趋势:自动化、电商与电动叉车的崛起
全球叉车市场到2032年将达到955.1亿美元,年复合增长率为7.49% | Astute Analytica 全球叉车市场正迎来显著增长,市场估值预计将从2023年的498.6亿美元增长至2032年的955.1亿美元,预测期内年复合增长率(CAGR)为7.49%。这…...
Kafka系列教程 - Kafka 生产者 -2
1. 生产者简介 不管是把 Kafka 作为消息队列系统、还是数据存储平台,总是需要一个可以向 Kafka 写入数据的生产者和一个可以从 Kafka 读取数据的消费者,或者是一个兼具两种角色的应用程序。 使用 Kafka 的场景很多,诉求也各有不同ÿ…...
【专题】2024年中国新能源汽车用车研究报告汇总PDF洞察(附原数据表)
原文链接: https://tecdat.cn/?p38564 本年度,国家及地方政府持续发力,推出诸多政策组合拳,全力推动汽车产业向更高质量转型升级,积极鼓励消费升级,并大力推行以旧换新等惠民生、促发展举措。尤为引人注目…...
将带注释的Word文档改造成点击注释引用即可弹窗显示注释的HTML文档
阅读中国古籍电子书的时候,往往有很多注释。在正文和注释之间来回滚动页面是一件挺麻烦的事,比较方便的做法是将它编辑成通过点击注释引用即将注释弹出显示在引用所在位置的HTML文档,然后利用HTML文档制作成PDF或者epub文件,就比较…...
【Android开发】安装Android Studio(2023.1.1)
下载安装包 Android Studio2023.1.1百度云盘下载,提取码:6666https://pan.baidu.com/s/1vNJezi7aDOP0poPADcBZZg?pwd6666 安装Android Studio 2023.1.1 双击下载好的安装包 弹出界面点击下一步 继续点击【Next】 更改安装路径后继续点击【Next】 点…...
SQLite Truncate Table
SQLite Truncate Table SQLite 是一种轻量级的数据库管理系统,广泛用于各种应用程序中。在数据库管理中,有时候需要快速删除表中的所有数据,这时就可以使用 TRUNCATE TABLE 命令。然而,SQLite 与其他数据库管理系统(如…...
港科夜闻 | 香港科大与荷兰代尔夫特理工大学(TU Delft)建立合作伙伴关系,推动艺术科技教育与研究...
关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与荷兰代尔夫特理工大学(TU Delft)建立合作伙伴关系,推动艺术科技教育与研究。2024年12月6日,合作伙伴计划正式启动,双方期望透过合作加强艺术科技知识交流,借此推…...
谈一谈大数据流式处理,以Spark Streaming为例详细论述
Spark Streaming是构建在Spark上的实时流计算框架,可以进行实时流数据处理。Spark是一个类似于MapReduce的分布式计算框架,其核心是弹性分布式数据集,可以在快速在内存中对数据集进行多次迭代,以支持复杂的数据挖掘算法和图形计算…...
RabbitMQ实现消息发送接收——实战篇(路由模式)
本篇博文将带领大家一起学习rabbitMQ如何进行消息发送接收,我也是在写项目的时候边学边写,有不足的地方希望在评论区留下你的建议,我们一起讨论学习呀~ 需求背景 先说一下我的项目需求背景,社区之间可以进行物资借用,…...
Docker Desktop占用空间问题解决
Windows安装Docker Desktop,没过多久就会发现C盘空间满了,很大可能是Docker Desktop的文件占用了空间,可以通过以下步骤解决: 步骤一:执行清理命令 docker system prune清理磁盘,删除关闭的容器、无用的数…...
系统性能优化
一、概述 性能优化的目标:是提高系统或应用程序的响应时间、吞吐量、cpu、内存、磁盘IO、网络、流量、JVM、Tomcat、DB等方面的性能指标。 性能优化需要有一些技巧:对于整个产品或项目而言,比如可以从前端优化、后端优化、架构优化、高并发…...
golang操作sqlite3加速本地结构化数据查询
目录 摘要Sqlite3SQLite 命令SQLite 语法SQLite 数据类型列亲和类型——优先选择机制 SQLite 创建数据库SQLite 附加数据库SQLite 分离数据库 SQLite 创建表SQLite 删除表 SQLite Insert 语句SQLite Select 语句SQLite 运算符SQLite 算术运算符SQLite 比较运算符SQLite 逻辑运算…...
【NebulaGraph】mac通过Docker安装以及官方查询示例、以及索引详解还有数据构建案例(五)
【NebulaGraph】mac通过Docker安装以及官方查询示例 1. Docker安装NebulaGraph2. 官方查询示例3. Nebula Graph 的 Java 数据解析实践与指导4. 从零到一:如何构建一个企业股权图谱系统?5. Nebula Graph 索引详解6. nGQL 执行计划详解与调优7. 图数据库的…...
【一本通】家庭作业(贪心算法)
【一本通】家庭作业 C语言代码 💐The Begin💐点点关注,收藏不迷路💐 老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业…...
Kylin麒麟操作系统 | 网络链路聚合配置(team和bond)
目录 一、理论储备1. 链路聚合 二、任务实施1. team模式2. bond模式 一、理论储备 1. 链路聚合 链路聚合是指将多个物理端口捆绑在一起,形成一个逻辑端口,以实现出/入流量在各成员端口中的负载分担。链路聚合在增加链路带宽、实现链路传输弹性和冗余等…...
2024年软件测试面试题大全【含答案】
一、面试基础题 简述测试流程: 1、阅读相关技术文档(如产品PRD、UI设计、产品流程图等)。 2、参加需求评审会议。 3、根据最终确定的需求文档编写测试计划。 4、编写测试用例(等价类划分法、边界值分析法等)。 5、用例评审(…...
Stable Diffusion 提示词语法
1.提示词基础 1.提示词之间用英文逗号,分隔 2.提示词之间是可以换行的 3.权重默认为1,越靠前权重越高 4.数量控制在75个单位以内 2.提示词各种符号的意义 2.1 ()、[]、{}符号 权重值()小括号[]中括号{}大括号默认1111层()1.1[]0.9{}1.052层(()) 1.121.21[[]]0.920.81{{}}1.…...
Y20030004基于asp.net+Sql的环保网站的设计与实现(附源码 调试 文档)
环保网站的设计与实现 1.摘要要2. 系统功能3.功能结构图4.界面展示5.源码获取 1.摘要要 近几年国家对于环境管理是高度重视,尤其是对于环境生态的破坏与环境污染,已经严重影响到人类的生存和发展。为了使生态环境能够得到保护和改善,持续发展…...
OpenCV的简单练习
1、读取一张彩色图像并将其转换为灰度图。 import matplotlib.pyplot as pltimg plt.imread("./flower.png") # 灰度化 img_gray img[:,:,0]*0.299 img[:,:,1]*0.587 img[:,:,2]*0.114plt.subplot(121) plt.imshow(img) plt.subplot(122) plt.imshow(img_gray,c…...
VS2019中无法跳转定义_其中之一情况
我习惯了使用VS2019看stm的代码; 遇到的问题,在导入代码后,发现有些函数调用不能跳转到定义; 问题描述步骤 1、导入代码 2、跳转,无法跳转 1、中文路径 2、删除.vs文件 和网上查的都没办法解决 最后发现是VS不支持 …...
虚幻5描边轮廓材质
很多游戏内都有这种描边效果,挺实用也挺好看的,简单复刻一下 效果演示: Linethickness可以控制轮廓线条的粗细 这样连完,然后放到网格体细节的覆层材质上即可 可以自己更改粗细大小和颜色...
【C语言】多线程服务器
多线程服务器 多线程服务器步骤代码 多线程服务器 步骤 主线程创建子线程,用子线程和客户端通信。 步骤: 1.使用socket函数,获取一个socket文件描述符 2.使用setsockopt端口复用 3.使用bind函数允许客户端的哪些ip可以访问服务器 4.使用lis…...
跨平台轻量级RTSP技术设计和使用场景探讨
设计背景 跨平台内网超低延迟直播的创新引擎 为满足安防视频监控、教育培训、工业生产、医疗健康、智能物联网等内网超低延迟需求,避免让用户配置单独的服务器,大牛直播SDK在推送端发布了跨平台(Windows|Linux(含x86_64|aarch64…...
分解质因数
题目描述 给定 n个正整数a,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。 输入格式 第一行包含整数 n。 接下来 n行,每行包含一个正整数 a。 输出格式 对于每个正整数 aiai,按照从小到大的顺…...
wordpress建站--如何用Let‘s Encrypt给网站添加免费ssl证书,支持https访问
本文首发网站:https://www.click234.com 默认情况下我们的网站是http访问,为了增加访问安全性,我们需要添加ssl证书,支持采用https方式访问,今天我们来看下怎么创建免费的ssl证书--Lets Encrypt 使用 Certbot 自动化工…...
web实操7——ServletContext
概念 和服务器通信 功能 解释说明: mime:互联网中一种文件的类型,可以用servletContext对象来获取。 域对象:用来共享数据,里面有一些get,set,removeAttribute,只要搞清楚ServletContext对象的域的范围是什么 如何…...
Android中bindService和startService启动服务有何区别
Android中bindService和startService启动服务有何区别 bindService 和 startService 是 Android 中两种用于与 Service 交互的方式,它们的区别主要在于 生命周期管理 和 使用场景。以下是详细对比: 1. bindService方式 bindService 是一种绑定方式&am…...
Jupyter Notebook 切换虚拟环境
方法 切换到需要添加到Jupyter Notebook中的虚拟环境,执行: python -m ipykernel install --name Jupyter Notebook中显示的虚拟环境名称如果遇到 [Errno 13] Permission denied: /usr/local/share/jupyter类似的权限问题,可能是没有对应的…...
短波红外相机
短波红外相机搭载采用 SenSWIR 技术的 Sony 高灵敏度传感器,能捕获到400nm~1700nm范围的可见光-短波红外宽波段图像信息,该相机可替代传统的“可见光相机短波红外相机”双相机检测方案,降低系统成本、提高处理速度、扩大检测范围,…...
余弦相似度Cosine Sim
what 余弦相似度是一种用于度量向量相似性的metric。 c o s θ A . B ∣ A ∣ . ∣ B ∣ cos\theta \frac{A.B}{|A|.|B|} cosθ∣A∣.∣B∣A.B A.B:向量的内积|A|:向量的模长 c o s θ cos\theta cosθ:的范围$ [ -1 , 1 ] $ why 余弦…...
【从零开始的LeetCode-算法】1338. 数组大小减半
给你一个整数数组 arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。 返回 至少 能删除数组中的一半整数的整数集合的最小大小。 示例 1: 输入:arr [3,3,3,3,5,5,5,2,2,7] 输出:2 解释:选择 {3,7…...
测试工程师八股文05|功能测试、业务测试
一、基础概念 1、软件测试分类 1️⃣按照软件产生的阶段划分 单元测试:针对程序源代码进行测试【开发自测】集成测试:针对模块之间功能交互进行测试系统测试:对整个系统(功能、非功能)进行全面测试验收测试ÿ…...
【电源专题】开关转换器使能(EN)和欠压锁定(UVLO)为什么需要回滞?
在文章:【电源专题】案例:芯片规格书使能定义高电平最小阈值1.4V,那真的是到1.4V时才开始输出?_芯片的电流阀值-CSDN博客中我们提到一般来说开关转换器的使能脚是有一个回滞的,比如下图所示的芯片规格书...