前端面试:如何实现并发请求数量控制?

题目:实现一个并发请求函数concurrencyRequest(urls, maxNum)
要求如下:

  • 要求最大并发数 maxNum;
  • 每当有一个请求返回,就留下一个空位,可以增加新的请求;
  • 所有请求完成后,结果按照 urls 里面的顺序依次打出;

思路

首先是比较最大请求数量和总的urls的数量,如果urls数量更小,直接全部发送,然后返回结果;否则先发送最大的请求数量,发送一个将正在发送的数量减一,并追加一个新的请求,直到请求发送完毕,返回全部结果。

  1. 初始化结果数组和当前正在请求的数组: 我们需要一个数组来存储每个请求的结果,还需要一个数组来存储当前正在执行的请求。

  2. 编写一个异步函数来执行单个请求: 这个函数负责发送请求,并将结果存储到结果数组中。同时,它会从正在执行的请求数组中移除已完成的请求。

  3. 使用循环和 Promise实现并发请求: 我们使用循环来初始化一定数量的并发请求,并将它们加入到正在执行的请求数组中。

  4. 递归调用函数以填补新的请求: 在请求完成后,我们可以递归调用函数,从 URL 数组中取出新的请求,然后再次执行。

实现

async function concurrencyRequest(urls: string[], maxNum: number) {
  return new Promise((resolve) => {
    const results: any = [];
    const executing: any = [];
    const run = async (url: any) => {
      try {
        const response = await fetch(url);
        results.push(response);
        console.log("请求中", url);
      } catch (error) {
        results.push({ error: true, message: error.message });
      } finally {
        const index = executing.indexOf(url);
        if (index !== -1) {
          executing.splice(index, 1);
        }
      }

      if (urls.length > 0 && executing.length < maxNum) {
        const runUrl = urls.shift();
        run(runUrl);
        executing.push(runUrl);
      }
      if (urls.length === 0 && executing.length === 0) resolve(results);
    };

    // 初始化时,执行最多 maxNum 个请求
    for (let i = 0; i < Math.min(maxNum, urls.length); i++) {
      const url = urls.shift();
      run(url);
      executing.push(url);
    }
  });
}

// 使用
const urls = ["url1", "url2", "url3", 'url4','url5','url6', 'url7','url8'];
const maxNum = 3;

concurrencyRequest(urls, maxNum)
  .then(results => {
    console.log("结果", results);
  })
  .catch(error => {
    console.error("发生错误:", error);
  });

效果:
在这里插入图片描述
在这里插入图片描述

try/catch/finally

相信大家都会用try…catch吧, 这里简单介绍一下。在 JS中,try...catch 语句用于捕获异常,而 finally 语句块中的代码将在 try 块和任何 catch 块之后执行,无论是否发生异常。
无论是否发生异常,finally 块中的代码都会被执行。这意味着,无论 try 块中的代码是否成功执行,catch 块是否执行,finally 中的代码都将执行。

例如:

try {
  // 一些可能抛出异常的代码
  console.log("Try block");
  throw new Error("An error occurred");
} catch (error) {
  // 捕获异常的代码
  console.error("Catch block:", error.message);
} finally {
  // 无论是否发生异常,都会执行的代码
  console.log("Finally block");
}

// 输出:
// Try block
// Catch block: An error occurred
// Finally block
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值