background

When our application makes a lot of requests instantly, such as hundreds of thousands of HTTP requests (insufficient TCP connections can cause waiting), or when the number of call stacks stacks can cause memory overflow, we need to limit the number of HTTP connections.

Train of thought

Here’s the idea: Initialize a pool array as a concurrent pool, loop through the pool, call addTask over and over again, and use your own custom request function reqUST (which can be a Promise object wrapped in a network request, or whatever), Each task is wrapped in a Promise object that pops out of the connection pool and adds the new task push to the concurrent pool.

implementation

Approach 1- Not through promise.race

// Customize the request function
var request = url= > {
    return new Promise(resolve= > {
        setTimeout(() = > {
            resolve(` task${url}Complete `)},1000)
    }).then(res= > {
        console.log('External logic', res); })}// Add a task
function addTask(url){
    let task = request(url);
    pool.push(task); 
    task.then(res= > {
        // Remove the Promise task from the concurrency pool after the request ends
        pool.splice(pool.indexOf(task), 1);
        console.log(`${url}End, current number of concurrent requests:${pool.length}`);
        url = urls.shift();
        // // Each time the concurrent pool finishes running a task, another task is inserted
        if(url ! = =undefined){ addTask(url); }})}let urls =  ['bytedance.com'.'tencent.com'.'alibaba.com'.'microsoft.com'.'apple.com'.'hulu.com'.'amazon.com'] // Request an address
let pool = []/ / concurrent pool
let max = 3 // Maximum concurrency
// Loop through the pool first
while (pool.length < max) {
    let url = urls.shift();
    addTask(url)
}
Copy the code

The online preview

Approach 2- through promise.race

// Customize the request function
var request = url= > {
    return new Promise(resolve= > {
        setTimeout(() = > {
            resolve(` task${url}Complete `)},1000)
    }).then(res= > {
        console.log('External logic', res); })}// Add a task
function addTask(url){
    let task = request(url);
    pool.push(task); 
    task.then(res= > {
        // Remove the Promise task from the concurrency pool after the request ends
        pool.splice(pool.indexOf(task), 1);
        console.log(`${url}End, current number of concurrent requests:${pool.length}`); })}// Each time the concurrent pool finishes running a task, another task is inserted
function run(race){
    race.then(res= > {
        let url = urls.shift();
        if(url ! = =undefined){
            addTask(url);
            run(Promise.race(pool)); }})}let urls =  ['bytedance.com'.'tencent.com'.'alibaba.com'.'microsoft.com'.'apple.com'.'hulu.com'.'amazon.com'] // Request an address
let pool = []/ / concurrent pool
let max = 3 // Maximum concurrency
// Loop through the pool first
while (pool.length < max) {
    let url = urls.shift();
    addTask(url)
}
// Use the promise.race method to get a signal that a task in the concurrent pool has completed
let race = Promise.race(pool)
run(race)
Copy the code

The online preview

Other implementations

You can use third-party packages in NPM that implement this functionality, such as Async-pool, ES6-Promise-pool, p-limit