How Promises Control Concurrency

Background of the problem

A certain project page is very complicated. When entering the page initialization, a lot of http requests are generated, resulting in too many concurrent requests, which may cause the memory overflow of the call stack and cause the page to crash. Therefore, it is necessary to limit the number of requests concurrently;

Method to realize

method one

//自定义请求函数
const request = url => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(`请求${url}完成`)
        }, 1000)
    }).then(res => {
        console.log('外部逻辑', res);
    })
}

//添加请求
const addRequest = (url) => {
    let requestTask = request(url);
    container.push(requestTask); 
    requestTask.then(res => {
        //请求结束后将该Promise任务从并发池中移除
        pool.splice(container.indexOf(requestTask), 1);
        console.log(`${url} 结束,当前并发数:${container.length}`);
        url = urls.shift();
        //每当并发池完成一个任务,同时添加一个任务
        if(url !== undefined){
            addRequest(url);
        }
    })
}

let requestUrls =  ['xxx1.com','xxx2.com','xxx3.com','xxx4.com','xxx5.com','xxx6.com','xxx7.com'] // 请求地址
let container = []//并发请求容器
let max = 3 //最大并发请求数量
//先循环把并发池塞满
while (container.length < max) {
    let requestUrl = requestUrls.shift();
    addTask(requestUrl)
}

way two

//自定义请求函数
const request = url => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(`请求${url}完成`)
        }, 1000)
    }).then(res => {
        console.log('外部逻辑', res);
    })
}

//添加请求任务
const addTask = (url) => {
    let task = request(url);
    pool.push(task); 
    task.then(res => {
        //请求结束后将该Promise任务从并发池中移除
        pool.splice(pool.indexOf(task), 1);
        console.log(`${url} 结束,当前并发数:${pool.length}`);
    })
}
每当并发池完成一个任务,同时添加一个任务
const run = (hasFinishTask) => {
    hasFinishTask.then(res => {
        let url = requestUrls.shift();
        if(url !== undefined){
            addTask(url);
            run(Promise.race(container));
        }
    })
}

let requestUrls =  ['xxx1.com','xxx2.com','xxx3.com','xxx4.com','xxx5.com','xxx6.com','xxx7.com'] // 请求地址
let container = []//并发请求容器
let max = 3 //最大并发请求数量
//先循环把并发池塞满
while (container.length < max) {
    let requestUrl = requestUrls.shift();
    addTask(requestUrl)
}
//利用Promise.race方法来获得并发池中某任务完成的信号
let hasFinishTask = Promise.race(container)
run(hasFinishTask)

write at the end

The difference between the two methods provided above is that the second method uses the Promise.race() method to obtain the signal of the completion of the task in the concurrent pool, delete the task, and add the task again; the unified idea of ​​the two methods is:

  • Initialize an array to store concurrent requests

  • Initialize a maximum concurrency variable

  • The loop fills the array with concurrent requests

  • After each request is initiated, delete this request and add a new request to the array of concurrent requests

The above is the idea of ​​​​realizing Promise concurrent requests. If you have other implementation methods, welcome to leave a message for exchange.

Guess you like

Origin blog.csdn.net/qq_44588612/article/details/128626581