promise限制并发请求数量

2023-05-16

所谓并发请求,就是指在一个时间点多个请求同时执行。当并发的请求超过一定数量时,会造成网络堵塞,服务器压力大崩溃或者其他高并发问题,此时需要限制并发请求的数量。

假如等待请求接口1000个,限制每次只能发出100个。即同一时刻最多有100个正在发送的请求。每当100个之中有一个请求完成时,则从待请求的接口(即剩余的900个待请求接口)中再取出一个发出。保证当前并发度仍旧为100。直至全部接口请求完成。

	// api接口请求列表
	const apiList = [
	    'url___A',
	    'url___B',
	    'url___C',
	    'url___D',
	    'url___E',
	    'url___F',
	    'url___G',
	]
	
	// 记录当前正在请求的接口,调试代码用
	let currentRequestList = []
     
        
	// 模拟请求数据
    const request = api => {
        console.log(`${api} 请求start`)
        // 请求时间 0 ~ 3 秒
        const wait = Math.random() * 3000
        console.log(`${api} 请求时间 ${wait}`)
        // currentRequestList 收集正在请求的接口
        currentRequestList.push(api)
        // 满足限制条件时,控制台显示当前正在请求的接口
        if (currentRequestList.length === 2) {
            console.log('当前正在请求的接口 -> ', currentRequestList.toString())
        }
        return new Promise(resolve => {
            setTimeout(() => {
                console.log(`${api} 请求end`)
                // 请求完成时,currentRequestList 删除该请求
                const index = currentRequestList.findIndex(c => c === api)
                currentRequestList.splice(index, 1)
                resolve(`获取接口“${api}”的数据`)
            }, wait)
        })
    }
	/**
	 * @descriptio 并发请求且限制请求数量
	 * @param {apiList} 请求接口列表
	 * @param {limit} 限制请求接口的数量,默认每次最多发送3次请求
	 * @param {callback} 回调函数
	 */		
    const requestWithLimit = (apiList, limit = 3, callback) => {

        // 请求数量记录,默认为 0
        let count = 0

        // 递归调用,请求接口数据
        const run = () => {
            // 接口每调用一次,记录数加 1
            count++
            const api = apiList.shift()
            request(api).then(res => {
                // 接口调用完成,记录数减 1
                count--
                console.log(res)
                // apiList 长度不为 0 且记录小于限制的数量时递归调用
                if (apiList.length && count < limit) {
                    run()
                }
                // apiList 为空且记录数减为初始值 0 时调用回调函数
                if (!apiList.length && !count) {
                	// 这里可以对所有接口返回的数据做处理,以便输出
                    callback('全部执行完毕!')
                }
            })
        }

        // 根据 limit 并发调用
        for (let i = 0; i < limit; i++) {
            run()
        }
    }
	
	requestWithLimit(apiList, 2, res => {
		console.log('回调函数', res)
	})

在这里插入图片描述

用人说用 for 循环来并发太 low 了,能否采用 Promise.all 的写法呢? 这个想法很不错,答案是可以的。Promise.all 接收一个元素为 Promise 对象的数组作为参数,这里控制并发的本质就是控制该数组的长度。

Promise.all([p1, p2, p3...])  		// p1, p2, p3...为 Promise 对象
	/**
	 * @description 限制并发请求
	 * @param {apiList} 请求接口列表
	 * @param {limit} 限制请求接口的数量,默认每次最多发送3次请求
	 * @return { Promise<Array> } resList
	 */
	 // 这里没有 callback 是因为返回的是 Promise 对象,其 then 方法取代了 callback
    const requestWithLimit = (apiList, limit = 3) => {
    	// apiList 的副本,避免 shift 方法对参数造成影响
        let list = [...apiList]
        // 用来记录api - response 的映射
  		// 保证输出与输入顺序一致
        let map = new Map()
        // 递归调用
        const run = () => {
            if (list.length) {
                const api = list.shift()
                return request(api).then(res => {
                    map.set(api, res)
                    return run()
                })
            }
        }
        // 当 apiList.length < limit 的时候,避免创建多余的 Promise
        const promiseList = Array(Math.min(apiList.length, limit)).fill(Promise.resolve()).map(promise => promise.then(run))
        return Promise.all(promiseList).then(() => {
            return apiList.map(c => map.get(c))
        })
    }
    
	requestWithLimit(apiList, 2).then(res => {
		console.log('请求完毕:', res)
	})

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

promise限制并发请求数量 的相关文章

  • “catch”在原生 Promise 链中如何工作?

    在 Chrome 或 Firefox 的控制台选项卡上尝试这段代码 var p new Promise function resolve reject setTimeout function reject 10 1000 p then fu
  • 如何使用带有 Promise 的 Socket.IO?

    作为持续努力的一部分 我正在将当前的回调技术更改为使用承诺blue bird承诺图书馆 我也想用 Socket IO 来实现这项技术 如何使用带有承诺而不是回调的 Socket IO 有没有使用 Socket IO 的标准方法 有官方解决方
  • 在 jQuery 中取消延迟的 Promise

    如何在不从 DOM 中删除元素的情况下取消 Promise fiddle http jsfiddle net ripper234 LG9eZ 4 我运行了这段代码 box delay 2000 show slow delay 2000 pr
  • NodeJS My SQL 查询与 Chain Promise

    我有3个函数 我想逐步调用这个函数 例如当我调用第一个函数并获取结果时 我必须调用第二个函数并传递从第一次调用返回的参数 在完成第二个调用后 我必须调用第三个函数并传递从第二个函数返回的参数 1 getCategory function b
  • JS/ES 离线并存储 Promise 供以后使用

    我如何才能取消这个 示例 承诺 即 将承诺归因于变量以供以后传递 使用 this example promise works OK just test with x 0 and x lt gt 0 var x 0 new Promise a
  • 为什么用 p.then(resolve) 比用resolve(p) 更早地解决新的 Promise?

    Code 1 和 Code 2 之间的区别是 Code 1 使用resolve p 和代码 2 使用p then gt resolve 我希望输出的序列是不变的 但它们会生成不同的序列 我不明白为什么 代码 1 resolve p cons
  • Javascript for 循环 Promise

    我有一个像这样的网址数组 var urls www google com www yahoo com 我想循环遍历 url 并在循环内执行异步任务 并且在异步任务完成之前不会继续执行下一个项目 我知道你可以通过承诺做到这一点 但我在这方面遇
  • 无法使用 JavaScript Promise 读取未定义的属性“then”

    我明白乍一看这可能看起来像重复的 但我已经看到了所有告诉我要退货的答案 但这不起作用 这是我的功能 function removePastUsersFromArray pullAllUsersFromDB then function use
  • 即使发生 400 bad request 错误,如何捕获服务器响应?

    考虑以下代码 这只是一个简单的 http post 请求axios图书馆 axios post http localhost users this state then function response if response statu
  • 等到作用域变量加载完毕后,再在 angular.js 的视图中使用它

    我见过this https stackoverflow com a 11972028 110233 and this https stackoverflow com questions 12265565 angularjs promise
  • 如何取消 Javascript Promise 内部的超时?

    我正在玩弄 JavaScript 中的承诺并尝试承诺 setTimeout 函数 function timeout ms return new Promise function resolve reject setTimeout funct
  • 蓝鸟承诺解析(数据)在客户端代码中未定义

    希亚斯 我有一个简单的应用程序 客户端期望得到一个承诺作为结果 但是在调用resolve 方法时 承诺不断返回未定义的结果 客户端代码 UsersRepo findOneAsync id id then function err resul
  • 在 Promise 链上使用 setTimeout

    在这里 我试图围绕承诺进行思考 在第一个请求中 我获取一组链接 在下一个请求中 我获取第一个链接的内容 但是我想在返回下一个承诺对象之前进行延迟 所以我使用setTimeout就可以了 但它给了我以下 JSON 错误 without set
  • 异步加载车把模板

    我正在尝试编写一个函数 该函数将为我提供一个已编译的车把模板 我将所有模板都放在单独的文件中 使用 ajax 调用来获取模板并编译它以供使用 但我需要使用承诺 以便我可以实际使用它 function getTemplate name get
  • Javascript -Uncaught 承诺被拒绝,即使它已经被拒绝

    我正在运行这个 Parse com 云代码作业 它查询我的一个类并获取 url 然后我读取这些 url 它们是 xml 文件 然后从其中获取一些数据并将其保存以进行解析 从代码中可以看出 这是代码 完整代码在这里gist github co
  • 为什么 .json() 是异步的? [复制]

    这个问题在这里已经有答案了 我一直在关注教程并发现以下代码片段 const myAsyncFunction async gt const usersResponse await fetch https jsonplaceholder typ
  • 在 mongoDB 中的同一 API 中并行查询同一文档

    我有一个用打字稿编写的 API 我尝试使用 Promise allsettled 对同一文档运行并行查询 但它的性能更差 我猜它们是按顺序运行的 有没有办法在 mongoDB 的同一连接中对同一文档执行并行查询 这是代码 console t
  • 可以或应该同时运行的 Promise 数量是否有限制?

    令人惊讶的是 谷歌无法返回这个问题的结果 我想知道在排队并等待下一个完成之前可以或应该并行运行多少个承诺 我想这可能取决于用户的互联网 但我认为值得一问 如果它基于用户的 ISP 连接类型 是否有办法在启动队列之前测试发送的理想承诺数量 另
  • 理解 JS Promise

    我想更深入地了解 Promise 内部是如何工作的 因此我有一些示例代码 var p1 new Promise function resolve reject window setTimeout function resolve res c
  • 你怎么知道无限长的承诺链何时完全结束?

    我试图使用 Promise 强制序列化一系列 Ajax 调用 用户每次按下按钮时都会进行这些 Ajax 调用 我可以成功地序列化操作 如下所示 sample async function real world this is an Ajax

随机推荐

  • 最详细的Gmapping代码详解!详细到每一行!

    无处不在的小土 gmapping的ROS封装 gaoyichao com
  • 【OpenCV3】棋盘格角点检测与绘制——cv::findChessboardCorners()与cv::drawChessboardCorners()详解

    棋盘格法是摄像机标定中常用的一种方法 xff0c 在使用该方法时需要对棋盘格的角点进行检测 opencv中封装了一个专门用于棋盘格角点检测的函数即cv findChessboardCorners xff0c 同时 xff0c 也提供了一个专
  • 网络编程和并发编程面试题

    网络编程和并发编程面试题 1 简述 OSI 七层协议 一 应用层 与其它计算机进行通讯的一个应用 xff0c 它是对应应用程序的通信服务的 例如 xff0c 一个没有通信功能的字处理程序就不能执行通信的代码 xff0c 从事字处理工作的程序
  • 树莓派利用串口进行通信

    树莓派串口通信 我用的是树莓派3b 43 型号 xff0c 网上各种各样的修改方式来使得树莓派的串口可以工作 xff0c 过于混乱 xff0c 还有的教程甚至会被树莓派系统搞崩溃 xff0c 尤其是树莓派实验室那里的中文教程 xff0c 是
  • Android系统学习(六)------裁剪Android系统

    你好 xff01 这里是风筝的博客 xff0c 欢迎和我一起交流 经过前面几篇博客的编译步骤 xff0c 成功的编出了Android系统 xff0c 但是发现编出来的system img有点大了 xff0c 有差不多1 7G xff0c 怎
  • 用postman批量执行post请求数据

    今天接到一个任务 xff0c 需要在同一个url中执行83次不同的post请求 xff0c 而且需要连续执行3次 xff0c 如果一个一个点击 xff0c 岂不是不符合 xff0c 摸鱼大王的风格 xff0c 思考片刻之后 xff0c 决定
  • 使用python批量发送post请求

    usr bin env python import requests url 61 34 http 192 168 26 xxx 34 header 61 39 Connection 39 39 close 39 39 Accept 39
  • 关于A 全球大气光 atmosphere light 算法总结

    由于大气散色所用引起的光源的特性 随着距离的增大而增强 A其实为无穷远处的一个大气光源 xff0c 比如天空 xff0c 这应该不是指天空中的云而是近地天空 由于各种去雾算法不同对A的依赖可能也不相同 我看到有几种方法对在去雾算法中应用 x
  • 解决树莓派开机黑屏不显示桌面问题

    一 设备状态 xff1a 以前桌面使用正常 xff0c 通过ssh进行安装pyqt5后导致桌面开机黑屏 二 所使用设备为 xff1a 树莓派4B 43 2021 05 07 raspios buster armhf img 三 定位问题 x
  • 树莓派Linux固定多USB设备号相同厂家设备和不同设备(包括一个USB设备两个设备名称号的情况)

    目录 一 问题说明 二 解决思路 三 开干 一 问题说明 在使用USB摄像头时 xff0c 由于使用了两个摄像头 xff0c 故此在上电启动后 xff0c 设备号会发生变化 xff0c 比如设备1之前时video0 xff0c 有的时候上电
  • FreeRTOS学习笔记-流缓冲区(FreeRTOS中文官网)

    https www freertos org zh cn cmn s RTOS stream buffer API html RTOS 流缓冲区 API RTOS 流缓冲区 API 函数 xff1a xStreamBufferCreate
  • FreeRTOS学习笔记-消息缓冲区(FreeRTOS中文官网)

    RTOS消息缓冲区 API RTOS 消息缓冲区 API 函数 xff1a xMessageBufferCreate xMessageBufferCreateStatic xMessageBufferSend xMessageBufferS
  • ubuntu系统X86环境下配置TX2的ARM环境的交叉编译链

    总步骤 安装qtcreator的IDE安装aarch64 linux gnu g 43 43 交叉编译链下载Qt库的源码 xff0c 配置编译选项 xff0c 编译生成针对TX2的ARM环境的qmake工具配置qtcreator xff0c
  • ROS中Eigen库的引用

    在CmakeList txt中添加两个地方 find package Eigen REQUIRED include directories Eigen INCLUDE DIR 如果找不到Eigen xff0c 我们将第一句改成 find p
  • ROS tf使用

    1 静态tf发布 lt node pkg 61 34 tf 34 type 61 34 static transform publisher 34 name 61 34 link1 link2 broadcaster 34 args 61
  • SLAM算法配置——使用Realsense D435i结合ROS跑通ORB-SLAM2的RGB-D节点

    ORB SLAM2源地址 配置环境依赖 Pangolin xff0c OpenCV xff0c Eigen3 xff0c DBoW2 and g2o xff08 源代码里有 xff0c 不用自己装 xff09 xff0c ROS xff08
  • 代码编写及阅读规范

    阅读常识 1 C语言中在函数名或关键字前加下划线 一般情况是标识该函数或关键字是自己内部使用的 xff0c 与提供给外部的接口函数或关键字加以区分 规范 综述 C 43 43 是一门十分复杂并且威力强大的语言 xff0c 使用这门语言的时候
  • 流媒体开发之路

    其实很早之前 xff0c 就想写属于自己的博客 xff0c 大二就有了CSDN账号 xff0c 很讽刺的是 xff0c 工作几年了 xff0c 账号里面的内容竟然和小鲜肉脸一样干净 干净的让人尴尬 回顾自己的这几年的开发之路 xff0c 接
  • matlab图像处理实例详解---note

    1 直方图均衡及直方图规定化 可以优化图像的亮度及gamma效果 2 图像的标准差 当图像越清晰的时候 xff0c 图像的标准差就越大 是否可以用来做af的判定标准 作为fv的值 另外是否可以用图像的相关系数作为caf的一个trigger
  • promise限制并发请求数量

    所谓并发请求 xff0c 就是指在一个时间点多个请求同时执行 当并发的请求超过一定数量时 xff0c 会造成网络堵塞 xff0c 服务器压力大崩溃或者其他高并发问题 xff0c 此时需要限制并发请求的数量 假如等待请求接口1000个 xff