1.第一种方法,推荐这种,核心是一句话,下面这段非常重要!!!!!
promise并不是因为调用Promise.all才执行,而是在实例化promise对象的时候就执行了,在理解这一点的基础上,要实现并发限制,只能从promise实例化上下手。 换句话说,就是把生成promises数组的控制权,交给并发控制逻辑。
直接上代码,代码清晰易懂。
var urls = [
'http://jsonplaceholder.typicode.com/posts/1',
'http://jsonplaceholder.typicode.com/posts/2',
'http://jsonplaceholder.typicode.com/posts/3',
'http://jsonplaceholder.typicode.com/posts/4',
'http://jsonplaceholder.typicode.com/posts/5',
'http://jsonplaceholder.typicode.com/posts/6',
'http://jsonplaceholder.typicode.com/posts/7',
'http://jsonplaceholder.typicode.com/posts/8',
'http://jsonplaceholder.typicode.com/posts/9',
'http://jsonplaceholder.typicode.com/posts/10'
]
function loadDate(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onload = function () {
resolve(xhr.responseText)
}
xhr.open('GET', url)
xhr.send()
})
}
const MAX_NUM = 3;
let WORKING_NUM = 0;
const start = function (){
for (let i = 0; i < MAX_NUM; i++) {
doNext();
}
}
const doNext = function () {
if (list.length && WORKING_NUM < MAX_NUM) {
WORKING_NUM++;
list.shift()().then((res)=>{
WORKING_NUM--;
doNext();
});
}
}
//这个地方非常重要,是核心,来控制promise开始执行,全靠这段,用一个外函数进行包装
let list = urls.map(url => {
return () => {
return loadDate(url);
}
})
start();
2.利用Set,来做阀门控制
const urls = [ 'http://jsonplaceholder.typicode.com/posts/1', 'http://jsonplaceholder.typicode.com/posts/2', 'http://jsonplaceholder.typicode.com/posts/3', 'http://jsonplaceholder.typicode.com/posts/4', 'http://jsonplaceholder.typicode.com/posts/5', 'http://jsonplaceholder.typicode.com/posts/6', 'http://jsonplaceholder.typicode.com/posts/7', 'http://jsonplaceholder.typicode.com/posts/8', 'http://jsonplaceholder.typicode.com/posts/9', 'http://jsonplaceholder.typicode.com/posts/10']
function loadDate(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onload = function () {
resolve(xhr.responseText)
}
xhr.open('GET', url)
xhr.send()
})
}
const MAX_NUM = 3
const executingTasks = new Set()
function fill() {
while (executingTasks.size < MAX_NUM && urls.length) {
const fn = loadDate(urls.shift())
.then(() => {
executingTasks.delete(fn);
fill();
})
executingTasks.add(fn)
}
}
fill()