有最大并发请求数限制的异步队列的最快请求算法

134 阅读1分钟

题目描述:

  1. 给定一个数组url,和浏览器最大异步请求数限制max,求解如何是的请求最快完成
  2. 要求返回的结果按照原数组url的顺序返回结果

实现方式1:

function doQuickly1(urls: string[], max: number) {
  const res: any = [];
  let maxPro = new Map<number, any>();
  let index = 0;

  function oneByOne(resolve: any) {
    if (index >= urls.length) {
      if (maxPro.size === 0) {
        resolve(res);
      }
      return;
    }

    while (maxPro.size <= max) {
      const pro = new Promise((resolve, reject) => {
        let temp = index;
        const time = Math.floor(Math.random() * 100);
        setTimeout(() => {
          console.log(`${temp}--urls[temp]]--${time}`);
          resolve([temp, urls[temp]]);
        }, time);
      });
      pro.then((result: [number, string]) => {
        res[result[0]] = result[1];
        maxPro.delete(result[0]);
        oneByOne(resolve);
      });
      maxPro.set(index, pro);
      index++;
    }
  }

  return new Promise((resolve, reject) => {
    oneByOne(resolve);
  });
}

实现方式2

async function doQuickly(urls: string[], max: number) {
  const res: any = [];
  let maxPro = new Map<number, any>();
  let index = 0;

  async function addPro() {
    if (index >= urls.length) {
      const lastTemp = await Promise.all(maxPro.values());
      if (!lastTemp) {
        return;
      } else {
        lastTemp.forEach((item) => {
          res[item[0]] = item[1];
        });
      }
      return;
    }
    while (maxPro.size < max && index < urls.length) {
      maxPro.set(
        index,
        new Promise((resolve, rej) => {
          let ti = index;
          const time = Math.floor(Math.random() * 1000);
          setTimeout(() => {
            console.log(`${ti}--${urls[ti]}--${time}`);
            resolve([ti, urls[ti]]);
          }, time);
        })
      );
      index = index + 1;
    }
    const temp = await Promise.race(maxPro.values());
    if (!temp) {
      return;
    } else {
      res[temp[0]] = temp[1];
      maxPro.delete(temp[0]);
      await addPro();
    }
  }

  await addPro();

  return res;
}