基于Promise实现一个限制并发请求的函数

基于Promise实现一个限制并发请求的函数

1. 首先模拟一下请求方法

let getRequestFn = function(time){
    return ()=>{
        return new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve(time)
            }, time);
        })
    }
} // 执行函数可返回一个自定义请求事件的函数,用来模拟请求

2. 实现一个限制并发数量的方法
首先我们可以思考一下如何可以限制并发,无非就是用一个循环来判断当前的执行个数,如果小于限制个数就再次发送请求,很多小伙伴可能会写出这样的代码,比如:

function request(tasks,pool){
    pool = pool || 5;
    let results = [];
    let running = 0;
    while(tasks.length > 0){ // 如果还有请求未执行
        if(running < pool) { // 如果小于并发次数 就再取出请求方法执行
            let task = tasks.shift();
            running++; 
            task().then(result => {
                results.push(result); // 将执行结果存入数组
                running --; // 当前执行个数减一
            });
        }
    }
}

我们很容易忽略一个问题,js是单线程的,函数执行过程中如果遇到异步任务,那么这个异步任务会退出主线程,存放到任务队列中等待执行,当主线程任务为空时才会执行异步任务,所以我们可以看到,代码中的running --; 这个操做是无法被操作到的。因为while一直在运行,导致异步任务无法获得主线程的执行。

使用递归实现限制并发数量的方法
// 要保证同时同时有pool个请求执行

function createRequest(tasks=[],pool){
    pool = pool || 5; //限制并发的数量
    let results = [];
    let running = 0; // 当前运行个数
    let resultsLength = tasks.length; // 用来判断最后的是否全部成功
    return new Promise((resolve,reject)=>{
        next();
        function next(){
            while(running < pool && tasks.length){ // 这个wile循环保证 一直有pool个请求在进行
            running++;
            let task = tasks.shift();
            task().then(result => {
                results.push(result);
            }).finally(()=>{
                running--;
                next();
            })
            }
            if(results.length === resultsLength) { // 全部执行结束
                resolve(results);
            }
        }
    })
}

我们使用一个next函数来保证每次可以有怕pool个请求函数在执行,并且超过两个时就可以退出循环,这样可以执行到异步任务,使得running--;并且再次执行next()用来执行请求的函数,最后当全部请求完毕以后返回results,当然本函数没有处理请求失败的问题,大家有兴趣以可以添加。

  1. 测试
//创建模拟请求任务
let tasks = [getRequestFn(4000),getRequestFn(2000),getRequestFn(2000),getRequestFn(2000)];
// 发送请求 并发数为2
console.time();
createRequest(tasks,2).then((value)=>{
    console.log(value)
    console.timeEnd();
})
// 输出
[ 2000, 4000, 2000, 2000 ]
default: 6.016s
// 可以看到执行了6s 因为同时只有两个请求可以发送 2000, 4000 =》 2000 结束以后 又执行一个2000的 最后 4000结束 执行2000的 一共6s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,以下是一个简单的控制请求并发数的js函数: ```javascript function limitRequestConcurrency(urls, maxConcurrency, callback) { let activeRequests = ; let index = ; function next() { if (index === urls.length && activeRequests === ) { return; } while (activeRequests < maxConcurrency && index < urls.length) { const url = urls[index++]; activeRequests++; fetch(url) .then(response => response.json()) .then(data => { callback(data); }) .catch(error => { console.error(error); }) .finally(() => { activeRequests--; next(); }); } } next(); } ``` 这个函数接受三个参数: - `urls`:一个包含请求URL的数组。 - `maxConcurrency`:最大并发请求数。 - `callback`:请求成功后的回调函数,接受一个参数,即请求返回的数据。 函数内部使用了递归调用来控制并发数,当活跃请求数小于最大并发数时,就会发起新的请求,否则等待已有请求完成后再发起新的请求。 ### 回答2: 可以使用以下的JavaScript函数来控制请求并发数: ```javascript function controlConcurrency(requests, maxConcurrent) { const results = []; let currentConcurrent = 0; let i = 0; function handleRequest() { if (i >= requests.length) { // 所有请求处理完毕 return; } if (currentConcurrent >= maxConcurrent) { // 达到最大并发数,等待一段时间再处理下一个请求 setTimeout(handleRequest, 100); return; } // 处理请求 const request = requests[i]; const promise = request(); currentConcurrent++; promise .then(response => { // 处理请求结果 results.push(response); }) .finally(() => { // 无论请求成功或失败,都将并发数减1,然后处理下一个请求 currentConcurrent--; i++; handleRequest(); }); } // 开始处理请求 handleRequest(); // 返回Promise对象,当所有请求处理完毕时,将结果数组作为resolve参数 return new Promise(resolve => { setTimeout(() => { if (i >= requests.length && currentConcurrent === 0) { resolve(results); } }, 1000); // 超时时间,避免请求处理时间过长导致无法结束Promise }); } ``` 这个函数接收两个参数:`requests`和`maxConcurrent`。`requests`是一个包含多个请求函数的数组,每个请求函数应该返回一个Promise对象。`maxConcurrent`表示最大的并发数。 函数会按照最大并发数依次处理请求,当达到最大并发数时,会等待一段时间再继续处理下一个请求。处理请求的过程使用递归实现,直到所有请求都处理完毕。 函数返回一个Promise对象,在所有请求处理完毕时,将结果数组作为resolve参数传递。你可以使用`.then()`方法来处理最终的结果。 ### 回答3: 当需要控制请求并发数时,可以使用以下的 JavaScript 函数实现: ```javascript function requestControlledConcurrency(urls, maxConcurrentRequests) { return new Promise((resolve, reject) => { let currentIndex = 0; let activeRequests = 0; let completedRequests = 0; let results = []; function makeRequest(url) { activeRequests++; return fetch(url) .then(response => { activeRequests--; completedRequests++; results.push(response); if (completedRequests === urls.length) { resolve(results); } else { processNextRequest(); } }) .catch(error => { reject(error); }); } function processNextRequest() { while (activeRequests < maxConcurrentRequests && currentIndex < urls.length) { makeRequest(urls[currentIndex]); currentIndex++; } } processNextRequest(); }); } ``` 这个函数接受两个参数:`urls` 是一个包含多个请求 URL 的数组,`maxConcurrentRequests` 是允许的最大并发请求数。函数会返回一个 Promise 对象,成功时返回包含所有请求结果的数组,失败时返回错误信息。 这个函数会依次发起请求,同时保持活动请求数不超过设定的最大并发请求数。在每次请求完成后,会判断是否还有未完成的请求,如果有则继续发起新的请求。只有当所有请求都完成后,Promise 才会被解析并返回结果数组。 可以按照以下示例使用这个函数: ```javascript const urls = ['url1', 'url2', 'url3', 'url4', 'url5']; const maxConcurrentRequests = 2; requestControlledConcurrency(urls, maxConcurrentRequests) .then(results => { console.log('所有请求完成'); console.log(results); }) .catch(error => { console.error('请求失败'); console.error(error); }); ``` 这个示例中,将同时发起两个请求,并且保持同时进行的请求不超过两个,直到所有请求完成。完成后,将会打印出所有请求的结果数组。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值