一、不使用Promise.race
维护一个并发池pool,先将其填满,然后每当其中的promise完成后添加新的promise,直到并发队列清空。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
let request = options =>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{resolve(options.url)},options.delay)
}).then((res)=>{
console.log(`${options.url}任务完成`)
})
}
let now = new Date()
function addTask(options){
let task = request(options)
pool.push(task)
task.then((res)=>{
pool.splice(pool.indexOf(task),1)
newOptions = requests.shift()
if(newOptions){
console.log(`${options.url}任务完成,耗时${(new Date()-now)/1000}秒,${newOptions.url}开始执行,预计耗时${newOptions.delay/1000}秒`)
addTask(options)
}else{
console.log(`${options.url}任务完成,耗时${(new Date()-now)/1000}秒`)
}
})
}
let requests = [{
url:'tencent',
delay:1000
},{
url:'baidu',
delay:3000
},{
url:'bytedance',
delay:2000
},{
url:'tieba',
delay:1000
},{
url:'bilibili',
delay:1000
},{
url:'acfun',
delay:1000
},{
url:'meituan',
delay:1000
}]
let pool = []
let max = 3
while(pool.length<max){
let options = requests.shift()
addTask(options)
}
</script>
</html>
二、使用Promise.race
原理类似,每当Promise.race()返回结果,就可以执行下一个promise了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
let request = options =>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{resolve(options.url)},options.delay)
}).then((res)=>{
console.log(`${options.url}任务完成`)
})
}
let now = new Date()
function addTask(options){
let task = request(options)
pool.push(task)
task.then((res)=>{
console.log(`${options.url}任务完成,耗时${(new Date()-now)/1000}秒`)
pool.splice(pool.indexOf(task),1)
})
}
function run(race){
race.then((res)=>{
let newOptions = requests.shift()
if(newOptions){
console.log(`${newOptions.url}开始执行,预计耗时${newOptions.delay/1000}秒`)
addTask(newOptions)
run(Promise.race(pool))
}
})
}
let requests = [{
url:'tencent',
delay:1000
},{
url:'baidu',
delay:3000
},{
url:'bytedance',
delay:2000
},{
url:'tieba',
delay:1000
},{
url:'bilibili',
delay:1000
},{
url:'acfun',
delay:1000
},{
url:'meituan',
delay:1000
}]
let pool = []
let max = 3
while(pool.length<max){
let options = requests.shift()
addTask(options)
}
let race = Promise.race(pool) // 返回最先完成的promise
run(race)
</script>
</html>