请求并发控制
请求并发数量控制
并发限制
要求:多个请求做并发限制,请求完成后执行回调
思路:
首次循环启动能够执行的任务
取出能执行的任务推入执行器执行
执行器更新当前并发数,并且再请求完成时继续取出任务推入执行器
当所有请求完成时,触发回调函数
function sendRequest(requestList, limits, callback) {const promises = requestList.slice(); // 取得请求list(浅拷贝一份)// 得到开始时,能执行的并发数const concurrentNum = Math.min(limits, requestList.length);let concurrentCount = 0; // 当前并发数// 第一次先跑起可以并发的任务const runTaskNeeded = () => {let i = 0;// 启动当前能执行的任务while (i < concurrentNum) {i++;runTask();}};// 取出任务并且执行任务const runTask = () => {const task = promises.shift();task && runner(task);};// 执行器// 执行任务,同时更新当前并发数const runner = async (task) => {try {concurrentCount++;const res = await task();console.log(res);} catch (error) {console.log(error);} finally {// 并发数--concurrentCount--;// 添加下一个任务picker();}};// 添加下一个任务const picker = () => {// 任务队列里还有任务并且此时还有剩余并发数的时候 执行if (concurrentCount < limits && promises.length > 0) {// 继续执行任务runTask();// 队列为空的时候,并且请求池清空了,就可以执行最后的回调函数了} else if (promises.length == 0 && concurrentCount == 0) {// 执行结束callback && callback();}};// 入口执行runTaskNeeded();}
测试一下上面的代码
function axios(url) {return new Promise((resolve, reject) => {setTimeout(() => {if (Math.random() > 0.6) {resolve("成功");} else {reject("失败");}}, Math.random() * 2000);});}const maxReqNum = 3,requestList = [];for (let k = 0; k < 15; k++) {requestList.push(axios);}sendRequest(requestList, maxReqNum, function () {console.log("所有请求完成");});
按照请求顺序返回结果
要求:多个请求做并发限制,并且所有请求完成时,按照请求顺序返回结果
思路:
并发限制发送请求,需要发送的请求数量如果不够就一次完成了所有请求
每次完成一个请求就产生了一个空位,可以继续发送新的请求,通过索引来保证顺序
所有请求完成后(加了一个变量统计请求完成请求数量,并在finally中修改),按照请求发送的顺序返回所有请求的结果
function requestLimit(urls, limit) {return new Promise((resolve) => {let index = 0; // 每次请求的索引// 存放所有请求的返回结果const resultList = [];if (urls.length === 0) return;const limit = Math.min(maxReqNum, urls.length); // 第一次发送多少个请求for (let i = 0; i < limit; i++) {request();}let finishedCount = 0; // 请求完成的数量// 发送请求function request() {const i = index; // i用来保证请求的顺序与相应顺序能对应上const url = urls[index];console.log(url);index++; // 每次发送一次请求加1,保证请求一个接一个axios(url).then((res) => {resultList[i] = res + i;}).catch((err) => {resultList[i] = err + i;}).finally(() => {finishedCount++;if (finishedCount === urls.length) {resolve(resultList); // 所有请求完成,修改promise状态}if (index < urls.length) {request(); // 没发送完一个请求,只要还有请求没有完成就继续发请求}});}});}// 模仿接口请求function axios(url) {return new Promise((resolve, reject) => {setTimeout(() => {if (Math.random() > 0.6) {resolve("成功");} else {reject("失败");}}, Math.random() * 5000);});}// 测试一下,maxReqNum:最大并发数,urls:所有需要发送的请求const maxReqNum = 3,urls = [];for (let k = 0; k < 15; k++) {urls.push(`https:www.test.com/${k}`);}requestLimit(urls, maxReqNum).then((res) => {console.log(res);}).catch((err) => {console.log(err);});
请求失败继续重新请求及重复请求次数限制
要求:多个请求做并发限制;当请求失败时,继续发送这个请求,直到请求成功或者达到了同一个请求重复请求次数的限制(请求算完成);所有请求完成时,按照请求顺序返回结果
思路:
在2的基础上;添加了一个failUrl来判断是不是继续重复请求失败的那个;如果重复的请求,就不会往正在请求的任务中添加新的任务,保证并发的限制;请求失败的时候,需要判断请求失败的次数,通过往请求的信息中添加了一个index(保证请求失败时拿到正确的对应重复请求信息)和count保证重复的请求达到限制就不再发送
// 发送请求的方法function request(url) {return new Promise((resolve, reject) => {setTimeout(() => {if (Math.random() > 0.6) {resolve("成功");} else {reject("失败");}}, Math.random() * 2000);});}function requestLimitFunc(maxReqNum, urlList, sameLimit) {return new Promise((resolve) => { let index = 0; // 通过索引,从urlList取出请求const resultList = []; // 保留请求结果的数组// 最多可以发多少个请求const limit = Math.min(maxReqNum, urlList.length);let finishCount = 0; // 有多少个请求已完成function activeTask(params) {for (let i = 0; i < limit; i++) {excuteTask();}}function excuteTask(failUrl) {let reqUrl = "";let i = 0;if (!failUrl) { i = index; // 如果传了failUrl,重新请求失败的那个,不需要往任务中添加请求了reqUrl = urlList[index].url;index++;} else { i = failUrl.reqIndex;reqUrl = failUrl.url;}request(reqUrl).then((res) => {finishCount++;resultList[i] = res;console.log(urlList[i].url, res);// 一个请求完成,需要添加新的请求进来if (index < urlList.length) excuteTask();}).catch((err) => {// 请求失败需要重新发送请求,直到请求成功或达到最多发送次数if (sameLimit === urlList[i].count) {finishCount++;resultList[i] = err;console.log("失败了", urlList[i].url);if (index < urlList.length) excuteTask();} else {urlList[i].count++;excuteTask(urlList[i]);}}).finally(() => {if (finishCount === urlList.length) resolve(resultList);});}activeTask(); // 第一次启动,在并发限制内发送最多的请求});}// 等待请求的数组const urlList = [];for (let i = 0; i < 15; i++) {urlList.push({reqIndex: i,count: 1,url: `https:www.test.com/${i}`,});}const maxReqNum = 5; // 最大并发数const sameLimit = 3; // 同一个请求失败重新请求,最多请求3次requestLimitFunc(maxReqNum, urlList, sameLimit).then((res) => {console.log(res);});
相关文章:
请求并发控制
请求并发数量控制 并发限制 要求:多个请求做并发限制,请求完成后执行回调 思路: 首次循环启动能够执行的任务 取出能执行的任务推入执行器执行 执行器更新当前并发数,并且再请求完成时继续取出任务推入执行器 当所有请求完…...
创建密码库/创建用户帐户/更新 Ansible 库的密钥/ 配置cron作业
目录 创建密码库 创建用户帐户 更新 Ansible 库的密钥 配置cron作业 创建密码库 按照下方所述,创建一个 Ansible 库来存储用户密码: 库名称为 /home/curtis/ansible/locker.yml 库中含有两个变量,名称如下: pw_developer&#…...
vue实现穿梭框,ctrl多选,shift多选
效果图 代码 <template><div class"container"><!--左侧--><div><div class"title">{{ titles[0] }}</div><div class"layerContainer"><div v-for"item in leftLayerArray":key"…...
Win11中zookeeper的下载与安装
下载步骤 打开浏览器,前往 Apache ZooKeeper 的官方网站:zookeeper官方。在主页上点击"Project"选项,并点击"Release" 点击Download按钮,跳转到下载目录 在下载页面中,选择版本号,并点…...
ubuntu22.04 找不到串口,串口ttyusb时断时续的问题(拔插以后能检测到,过会儿就检测不到了)
1. 问题描述 ubuntu22.04的PC,在连接USB串口的时候,有时能找到ttyUSB0,有时找不到,如下: base) airsairs-Precision-3630-Tower:~$ ls -l /dev/ttyUSB* crwxrwxrwx 1 root dialout 188, 0 Aug 17 16:36 /dev/ttyUSB0 (base) air…...
Pinia基础教程
Pinia wiki Pinia 起始于 2019 年 11 月左右的一次实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。从那时起,我们就倾向于同时支持 Vue 2 和 Vue 3,并且不强制要求开发者使用组合式 API,我们的初心至今没有改变。除了安…...
【NOIP】标题统计
author:&Carlton tags:模拟,字符串 topic:【NOIP】标题统计 language:C website:P5015 [NOIP2018 普及组] 标题统计 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) date:2023年8月20日…...
BOXTRADE-天启量化分析平台 系统功能预览
BOXTRADE-天启量化分析平台 系统功能预览 系统功能预览 1.登录 首页 参考登录文档 2. A股 行情与策略分析 2.1 A股股票列表 可以筛选和搜索 2.2 A股行情及策略回测 2.2.1 行情数据提供除权和前复权,后复权数据;外链公司信息 2.2.2 内置策略执行结果…...
解决Kibana(OpenSearch)某些字段无法搜索问题
背景 最近在OpenSearch查看线上日志的时候,发现某个索引下有些字段无法直接在界面上筛选,搜索到也不高亮,非常的不方便,就像下面这样 字段左侧两个筛选按钮禁用了无法点击,提示 Unindexed fields can not be searched…...
代码随想录训练营day15|102.层序遍历 226.翻转二叉树 101.对称二叉树
TOC 前言 代码随想录算法训练营day15 一、Leetcode 102.层序遍历 1.题目 给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:…...
Nginx 配置https以及wss
一、申请https证书 可以在阿里云申请免费ssl证书,一年更换一次 二、Nginx配置ssl upstream tomcat_web{server 127.0.0.1:8080; }server {listen 443 ssl;server_name www.xxx.com;## 配置日志文件access_log /var/log/nginx/web/xxx-ssl-access.log main;er…...
Log4net在.Net Winform项目中的使用
引言: Log4net是一个流行的日志记录工具,可以帮助开发人员在应用程序中实现高效的日志记录。本文将提供一个详细的分步骤示例,来帮助您在.Net Winform项目中使用Log4net。 目录 一、安装Log4net二、配置Log4net三、在项目中使用Log4net四、初…...
从零到一制作扫雷游戏——C语言
什么是扫雷游戏? 扫雷游戏作为一种老少咸宜的益智游戏, 它的游戏目标十分简单,就是要求玩家在最短的时间内, 根据点击格子之后所出现的数字来找出所有没有炸弹的格子, 同时在找的时候要避免点到炸弹,一…...
Python 数据挖掘与机器学习教程
详情点击链接:Python 数据挖掘与机器学习教程 模块一:Python编程 Python编程入门 1、Python环境搭建( 下载、安装与版本选择)。 2、如何选择Python编辑器?(IDLE、Notepad、PyCharm、Jupyter…ÿ…...
排序小白必读:掌握插入排序的基本原理
一、插入排序是什么? 它是一种简单直观的排序算法。类似于整理扑克牌,想象你手上有一堆未排序的牌,你将它们逐个插入已排序的牌堆中的正确位置。拿起一张牌,与已排序的牌进行比较,将它插入到合适的位置。重复这个过程…...
html常见兼容性问题
1. png24位的图片在iE6浏览器上出现背景 解决方案:做成PNG8,也可以引用一段脚本处理. 2. 浏览器默认的margin和padding不同 解决方案:加一个全局的 *{margin:0;padding:0;} 来统一。 3. IE6双边距bug:在IE6下,如果对…...
Docker实战:docker compose 搭建Redis
1、配置文件准备 redis 配置文件:https://pan.baidu.com/s/1YreI9_1BMh8XRyyV9BH08g2、创建目录并赋权 mkdir -p /home/docker/redis/data /home/redis/logs /home/redis/conf chmod -R 777 /home/docker/redis/data* chmod -R 777 /home/docker/redis/logs*3、re…...
Debian11 Crontab
Crontab用户命令 可执行文件 crontab命令的可执行文件在哪儿? $ which -a crontab /usr/bin/crontab /bin/crontabcrontab命令的可执行文件有2个:/usr/bin/crontab 和 /bin/crontab $ diff /usr/bin/crontab /bin/crontab $diff 发现这两个文件并无区…...
css 文字排版-平铺
序: 1、表格的宽度要有!!!!! 2、容器不能是display:inline 3、扩展---》node全栈框架 代码 text-align-last: justify; width: 70px; display: inline-block; 主要是用于表单左侧文字排序!...
把握潮流:服装定制小程序的发展与趋势
随着互联网的快速发展,小程序成为了人们生活中不可或缺的一部分。尤其在服装行业,定制化已经成为了一种趋势。为了满足消费者个性化的需求,服装定制小程序应运而生。 为了方便开发者的设计和制作,我们可以使用第三方的制作平台来创…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
