Promise并发数限制,头条阿里都考过

940 阅读1分钟

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()

3.利用递归

4.拓展Promise.each + 递归