问题分析

每个请求结束后,看队列中是否有未完成的请求,如果有,就按顺序进行下一个请求

代码实现

每个请求结束后再次调用

function multiRequest(urls = [], max) {
  const len = urls.length;
  const result = [];
  // 统计开始的请求
  let count = 0;
  // 统计结束的请求,全部结束后resolve一下
  let finished = 0;

  return new Promise((resolve, reject) => {
    const next = () => {
      let current = count++;
      
      fetchUrl(urls[current]).then(res => {
        result[current] = res;
      }).catch(err => {
        result[current] = err;
      }).finally(() => {
        finished++;
        if (count < len) {
          next();
        }
        if (finished === len) {
          resolve(result);
        }
      })
    }
    while(count < max) {
      next();
    }
  })
}

另外一种是基于 Promise.all 方式

// 基于Promise.all
function multiRequest(urls = [], max) {
  let len = urls.length;
  let count = 0;
  const result = [];

  return new Promise((resolve) => {
    const addTask = () => {
      if (count >= len) {
        return resolve();
      }
      result[count] = fetchUrl(urls[count]).then(res => {
        addTask();
        return res;
      });
      count++;
    }
    while(count < max) {
      addTask();
    }
  }).then(() => Promise.all(result))
}

还可以基于async/await实现

function multiRequestByAsync(urls = [], max) {
  const result = [];
  let count = 0;
  async function addTask() {
    if (count >= urls.length) {
      console.log(result);
      return;
    }
    const url = urls[count];
    try {
      const res = await fetchUrl(url);
      result[count] = res;
    } catch(e) {
      result[count] = e;
    } finally {
      addTask();
      count++;
    }
  }
  while (count < max) {
    addTask();
    count++;
  }
}
Last Updated:
Contributors: tiodot