并发请求控制

在这里插入图片描述

Chrome 浏览器最多并发6个请求。一般情况下,我们都会设置并发数为 3。

并发请求控制主要有两种区别:假设并发数为 3

  1. 三个请求为一组进行并发,这三个请求全部完成了,再进行下一组。
  2. 在第一种方式的基础上加上滑动补位,第一组三个请求,当其中一个请求完成,后续第4个请求,迅速补上发起请求。

这两种方式,第一种压根不是并发请求,准确说应该是并发发起请求。第二种有了滑动补位,才能说是一直以最大并发数在进行请求流程。

实现并发控制的核心:await Promise,将异步变同步

/**
 * 并发请求控制
 * @param {Function[]}requestArr 请求函数组成的数组
 * @param {number}limit 并发数量,默认为 3
 * @returns {Promise<any>[]} 每个请求的 promise 组成的数据
 */
export async function controlConcurrency(
    requestArr: ((...args: any[]) => Promise<any>)[],
    limit: number = 3
): Promise<any>[] {
    
    
    // 如果并发数小于等于0,抛出错误
    if (limit <= 0) throw new Error("并发限制必须大于0");

    const results: Promise<any>[] = []; // 结果数组
    const running: Promise<any>[] = []; // 并发数组

    // 遍历请求数组
    for (const request of requestArr) {
    
    
        // 调用请求函数,返回一个Promise
        const promise = request();

        // 将Promise添加到结果数组
        results.push(promise);

        // 将Promise添加到并发数组
        running.push(promise);

        // 如果并发数组的长度大于限制数,则等待running数组中最先完成的promise
        if (running.length >= limit) {
    
    
            await Promise.race(running);
        }

        // 每次Promise完成,从并发数组中移除
        promise.finally(() => {
    
    
            const index = running.indexOf(promise);
            if (index !== -1) running.splice(index, 1);
        });
    }

    // 返回所有Promise的结果
    return results;
}

测试代码:

const requestsArr = []

for (let index = 0; index < 10; index++) {
    
    
  requestsArr[index] = () => fetch('http://localhost/user')
}

controlConcurrency(requestsArr, 2).forEach(item => {
    
    
	item.then(response => {
    
    
	    response.json().then(res => {
    
    
	      	console.log(res);
	    })
  	})
  	.catch(err => {
    
    
	  	console.log(err);
	})
})

测试接口:

const express = require('express')

const app = new express()

// 跨域
app.all('*', function (req, res, next) {
    
    
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Methods', '*');
  res.header('Content-Type', 'application/json;charset=utf-8');
  next();
});

function getRandom() {
    
    
  return Math.floor(Math.random() * 10) + 1
}

app.get('/user', (req, res) => {
    
    
  const d = getRandom()
  // 随机延迟响应
  setTimeout(() => {
    
    
    res.json({
    
    time: d}) 
  }, d * 500)
})


app.listen(80, ()=> {
    
    
  console.log("express server running at http://127.0.0.1:80")
})

猜你喜欢

转载自blog.csdn.net/qq_43220213/article/details/134194533
今日推荐