请求并发控制
请求并发数量控制
并发限制
要求:多个请求做并发限制,请求完成后执行回调
思路:
首次循环启动能够执行的任务
取出能执行的任务推入执行器执行
执行器更新当前并发数,并且再请求完成时继续取出任务推入执行器
当所有请求完成时,触发回调函数
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; 主要是用于表单左侧文字排序!...
把握潮流:服装定制小程序的发展与趋势
随着互联网的快速发展,小程序成为了人们生活中不可或缺的一部分。尤其在服装行业,定制化已经成为了一种趋势。为了满足消费者个性化的需求,服装定制小程序应运而生。 为了方便开发者的设计和制作,我们可以使用第三方的制作平台来创…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
