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

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

题目:实现一个并发请求函数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
目录
相关文章
|
6天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
29天前
|
前端开发 JavaScript
回顾前端页面发送ajax请求方式
回顾前端页面发送ajax请求方式
36 18
|
19天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
54 1
|
1月前
|
前端开发 JavaScript API
前端Get请求能在body上传参吗
【10月更文挑战第11天】 在浏览器环境中,GET请求的body参数会被忽略,这是因为浏览器中的XHR和fetch实现限制了这一行为。而在Node.js服务端环境中,GET请求可以在body中传递参数,因为服务端请求库没有这样的限制。实际上,GET请求不带body是HTTP标准的一部分,但在某些场景下,为了遵循RESTful规范,可以考虑通过服务端转发或BFF模式来实现复杂的参数传递。
|
2月前
|
Web App开发 前端开发 Linux
「offer来了」浅谈前端面试中开发环境常考知识点
该文章归纳了前端开发环境中常见的面试知识点,特别是围绕Git的使用进行了详细介绍,包括Git的基本概念、常用命令以及在团队协作中的最佳实践,同时还涉及了Chrome调试工具和Linux命令行的基础操作。
「offer来了」浅谈前端面试中开发环境常考知识点
|
1月前
|
存储 缓存 监控
|
1月前
|
移动开发 前端开发 HTML5
SharedWorker 优化前端轮询请求
【10月更文挑战第6天】
22 1
|
30天前
|
Web App开发 JavaScript 前端开发
前端Node.js面试题
前端Node.js面试题
|
1月前
|
Java 调度 Android开发
Android面试题之Kotlin中async 和 await实现并发的原理和面试总结
本文首发于公众号“AntDream”,详细解析了Kotlin协程中`async`与`await`的原理及其非阻塞特性,并提供了相关面试题及答案。协程作为轻量级线程,由Kotlin运行时库管理,`async`用于启动协程并返回`Deferred`对象,`await`则用于等待该对象完成并获取结果。文章还探讨了协程与传统线程的区别,并展示了如何取消协程任务及正确释放资源。
23 0
|
2月前
|
前端开发 JavaScript API
前端性能优化-控制并发
【9月更文挑战第7天】前端性能优化-控制并发
31 0