当前位置: 首页 > news >正文

请求并发控制

请求并发数量控制

并发限制

要求:多个请求做并发限制,请求完成后执行回调

思路

首次循环启动能够执行的任务

取出能执行的任务推入执行器执行

执行器更新当前并发数,并且再请求完成时继续取出任务推入执行器

当所有请求完成时,触发回调函数

      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);});

相关文章:

请求并发控制

请求并发数量控制 并发限制 要求&#xff1a;多个请求做并发限制&#xff0c;请求完成后执行回调 思路&#xff1a; 首次循环启动能够执行的任务 取出能执行的任务推入执行器执行 执行器更新当前并发数&#xff0c;并且再请求完成时继续取出任务推入执行器 当所有请求完…...

创建密码库/创建用户帐户/更新 Ansible 库的密钥/ 配置cron作业

目录 创建密码库 创建用户帐户 更新 Ansible 库的密钥 配置cron作业 创建密码库 按照下方所述&#xff0c;创建一个 Ansible 库来存储用户密码&#xff1a; 库名称为 /home/curtis/ansible/locker.yml 库中含有两个变量&#xff0c;名称如下&#xff1a; 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的下载与安装

下载步骤 打开浏览器&#xff0c;前往 Apache ZooKeeper 的官方网站&#xff1a;zookeeper官方。在主页上点击"Project"选项&#xff0c;并点击"Release" 点击Download按钮&#xff0c;跳转到下载目录 在下载页面中&#xff0c;选择版本号&#xff0c;并点…...

ubuntu22.04 找不到串口,串口ttyusb时断时续的问题(拔插以后能检测到,过会儿就检测不到了)

1. 问题描述 ubuntu22.04的PC&#xff0c;在连接USB串口的时候&#xff0c;有时能找到ttyUSB0,有时找不到&#xff0c;如下&#xff1a; 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 月左右的一次实验&#xff0c;其目的是设计一个拥有组合式 API 的 Vue 状态管理库。从那时起&#xff0c;我们就倾向于同时支持 Vue 2 和 Vue 3&#xff0c;并且不强制要求开发者使用组合式 API&#xff0c;我们的初心至今没有改变。除了安…...

【NOIP】标题统计

author&#xff1a;&Carlton tags&#xff1a;模拟&#xff0c;字符串 topic&#xff1a;【NOIP】标题统计 language&#xff1a;C website&#xff1a;P5015 [NOIP2018 普及组] 标题统计 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) date&#xff1a;2023年8月20日…...

BOXTRADE-天启量化分析平台 系统功能预览

BOXTRADE-天启量化分析平台 系统功能预览 系统功能预览 1.登录 首页 参考登录文档 2. A股 行情与策略分析 2.1 A股股票列表 可以筛选和搜索 2.2 A股行情及策略回测 2.2.1 行情数据提供除权和前复权&#xff0c;后复权数据&#xff1b;外链公司信息 2.2.2 内置策略执行结果…...

解决Kibana(OpenSearch)某些字段无法搜索问题

背景 最近在OpenSearch查看线上日志的时候&#xff0c;发现某个索引下有些字段无法直接在界面上筛选&#xff0c;搜索到也不高亮&#xff0c;非常的不方便&#xff0c;就像下面这样 字段左侧两个筛选按钮禁用了无法点击&#xff0c;提示 Unindexed fields can not be searched…...

代码随想录训练营day15|102.层序遍历 226.翻转二叉树 101.对称二叉树

TOC 前言 代码随想录算法训练营day15 一、Leetcode 102.层序遍历 1.题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 (即逐层地&#xff0c;从左到右访问所有节点)。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a…...

Nginx 配置https以及wss

一、申请https证书 可以在阿里云申请免费ssl证书&#xff0c;一年更换一次 二、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项目中的使用

引言&#xff1a; Log4net是一个流行的日志记录工具&#xff0c;可以帮助开发人员在应用程序中实现高效的日志记录。本文将提供一个详细的分步骤示例&#xff0c;来帮助您在.Net Winform项目中使用Log4net。 目录 一、安装Log4net二、配置Log4net三、在项目中使用Log4net四、初…...

从零到一制作扫雷游戏——C语言

什么是扫雷游戏&#xff1f; 扫雷游戏作为一种老少咸宜的益智游戏&#xff0c; 它的游戏目标十分简单&#xff0c;就是要求玩家在最短的时间内&#xff0c; 根据点击格子之后所出现的数字来找出所有没有炸弹的格子&#xff0c; 同时在找的时候要避免点到炸弹&#xff0c;一…...

Python 数据挖掘与机器学习教程

详情点击链接&#xff1a;Python 数据挖掘与机器学习教程 模块一&#xff1a;Python编程 Python编程入门 1、Python环境搭建&#xff08; 下载、安装与版本选择&#xff09;。 2、如何选择Python编辑器&#xff1f;&#xff08;IDLE、Notepad、PyCharm、Jupyter…&#xff…...

排序小白必读:掌握插入排序的基本原理

一、插入排序是什么&#xff1f; 它是一种简单直观的排序算法。类似于整理扑克牌&#xff0c;想象你手上有一堆未排序的牌&#xff0c;你将它们逐个插入已排序的牌堆中的正确位置。拿起一张牌&#xff0c;与已排序的牌进行比较&#xff0c;将它插入到合适的位置。重复这个过程…...

html常见兼容性问题

1. png24位的图片在iE6浏览器上出现背景 解决方案&#xff1a;做成PNG8&#xff0c;也可以引用一段脚本处理. 2. 浏览器默认的margin和padding不同 解决方案&#xff1a;加一个全局的 *{margin:0;padding:0;} 来统一。 3. IE6双边距bug&#xff1a;在IE6下&#xff0c;如果对…...

Docker实战:docker compose 搭建Redis

1、配置文件准备 redis 配置文件&#xff1a;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命令的可执行文件在哪儿&#xff1f; $ which -a crontab /usr/bin/crontab /bin/crontabcrontab命令的可执行文件有2个&#xff1a;/usr/bin/crontab 和 /bin/crontab $ diff /usr/bin/crontab /bin/crontab $diff 发现这两个文件并无区…...

css 文字排版-平铺

序&#xff1a; 1、表格的宽度要有&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 2、容器不能是display:inline 3、扩展---》node全栈框架 代码 text-align-last: justify; width: 70px; display: inline-block; 主要是用于表单左侧文字排序&#xff01;...

把握潮流:服装定制小程序的发展与趋势

随着互联网的快速发展&#xff0c;小程序成为了人们生活中不可或缺的一部分。尤其在服装行业&#xff0c;定制化已经成为了一种趋势。为了满足消费者个性化的需求&#xff0c;服装定制小程序应运而生。 为了方便开发者的设计和制作&#xff0c;我们可以使用第三方的制作平台来创…...

Go 安装配置

介绍Ubuntu20.04 安装和配置Go 可以参考官网的这个为 Go 开发配置Visual Studio Code - Go on Azure | Microsoft Learn 1.安装Go 去这个地方下载Go https://go.dev/doc/install 如果之前安装过&#xff0c;可以参考这个&#xff08;没有可以忽略&#xff09; 下载完成后执…...

镜像底层原理详解和基于Docker file创建镜像

目录 一、镜像底层原理 1.联合文件系统(UnionFS) 2.镜像加载原理 3.为什么Docker里的centos的大小才200M? 二、Dockerfile 1.简介 2.Dockerfile操作常用命令 &#xff08;1&#xff09;FORM 镜像 &#xff08;2&#xff09;MAINTAINER 维护人信息 &#xff08;3&…...

k8s扩缩容与滚动更新

使用kubectl run创建应用 kubectl run kubernetes-bootcamp \> --imagedocker.io/jocatalin/kubernetes-bootcamp:v1 \> --port8080 端口暴露出去 kubectl expose pod kubernetes-bootcamp --type"NodePort" --port 8080 使用kubectl create创建应用 kubect…...

4.小程序的运行机制

启动过程 把小程序的代码包下载到本地解析app.json全局配置文件执行app.js小程序入口文件&#xff0c;调用App()创建小程序的实例渲染小程序首页小程序启动完成 页面渲染过程 加载解析页面的.json配置文件加载页面.wxml模板和.scss样式执行页面的.ts文件&#xff0c;调用Pag…...

基于 Vercel TiDB Serverless 的 chatbot

作者&#xff1a; shiyuhang0 原文来源&#xff1a; https://tidb.net/blog/7b5fcdc9 # 前言 TiDB Serverless 去年就有和 Vercel 的集成了&#xff0c;同时还有一个 bookstore template 方便大家体验。但个人感觉 bookstore 不够炫酷&#xff0c;借 2023 TiDB hackthon 的…...

Android 多渠道打包及VasDolly使用

目录 1.添加productFlavors的配置buildConfigFieldmanifestPlaceholdersresValue 2.设置apk文件的名称&#xff0c;便于识别3.添加vasdolly、添加gradle脚本&#xff08;windows&#xff09; 作用&#xff1a;一次性可以打多个apk包&#xff0c;名字、包名、logo等可以不相同。…...

LeetCode 42题:接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,…...

spring boot 提示:程序包不存在,解决方法总结

背景&#xff1a; 之前出现过这样的问题&#xff0c;打包安装父项目就好了&#xff0c;今天改了一下代码&#xff0c;重新编译的时候&#xff0c;又出现了这样的情况&#xff0c;决定深度挖掘一下这里面的问题 spring boot 提示&#xff1a;程序包不存在&#xff0c;解决方法总…...

docker项目实战

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘 1&#xff09;拉取mysql:5.6和owncloud镜像 [rootmaster ~]# docker pull mysql:5.6 5.6: Pulling from library/mysql 35b2232c987e: Pull complete fc55c00e48f2: Pull complete 0030405130e3: Pull compl…...

银行客户关系管理系统springboot财务金融进销存java jsp源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 银行客户关系管理系统springboot 系统有1权限&#x…...