实现一个mapLimit

实现一个mapLimit(异步并发控制)

核心主要是异步流程的控制,
核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let index = 0,
completed = 0,
running = 0;
function next(){
console.info('running:',running," index:",index," completed:",completed)
//如果 当前运行任务数量小于 并发限制数量 且 完成的任务数小于总任务数目,则取出下一个任务执行,在其回调中, 让running--, complete++;并且执行下一个next();执行完任务行后, running++;
while ( running < concurrency && index < tasks.length ) {
task = tasks[index++]
task(()=>{
running--
completed++
if ( completed == tasks.length ){
return callback()
}
next()
})
running++
}
}
next()

全部代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function mapLimit ( tasks, concurrency=1, callback ) {
if(!Array.isArray(tasks)) throw new Error('first argument must be array')
if(typeof(concurrency)!='number') throw new Error('second argument must be number')
if(typeof(callback)!='function') throw new Error('third argument must be function')
let index = 0,
completed = 0,
running = 0
function next(){
console.log(`running:${running},concurrency:${concurrency},completed:${completed}`);
while ( running <= concurrency && index < tasks.length ) {
task = tasks[index++]
task(()=>{
running--
completed++
if ( completed == tasks.length ){
return callback()
}
next()
})
running++
}
}
next()
}

随便开一个百度首页测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//
function generateTask(num = 100){
let tasks = [];
function fetchData(callback) {
return fetch(location.href+'?'+Math.random())
.then()
.then(()=>{
callback()
})
}
for (let i = 0; i < num; i++) {
tasks.push(fetchData)
}
return tasks;
}

var tasks = generateTask(1e2)

mapLimit(tasks,50,function(){console.log('全部任务结束!')})


end