前端高频面试题-并发请求

  • 面试题中,有一道题经常会出现,咱们下面讲一下思路以及写法
  • 写一个方法,传入一个请求地址数组,以及一个并发数量,根据并发数量,一起发送请求。如果一个发送完,那么从数组中拿出来一个接着发送,最多一起发送三个,直到结束为止。并且这个方法最终返回的结果为前面多个请求结果组成的数组,且结果顺序和请求地址数组顺序一致。

1.编写方法基本框架

/**
 *
 * @param {Array} urls 请求的url列表
 * @param {Number} maxNum 最大并发数
 * @returns
 */
function sendPostRequestInParallel(urls, maxNum) {
  // 如果 urls 为空,直接返回一个空数组
  if (urls.length === 0) {
    return Promise.resolve([]);
  }
    
  // 结果为成功的,如果请求失败的话,把失败原因放数组中即可
  return new Promise((resolve) => {});
}

const urls = [];
for (let i = 1; i <= 10; i++) {
  urls.push(`http://localhost:8888/testTcc?num=${i}`);
}

// 10个url,每次3个并发
const resList = await sendPostRequestInParallel(urls, 3);
console.log(resList);

2.内部方法,每次获取一条并发送

![test](C:/Users/tcc-computer/Pictures/test.gif)/**
 *
 * @param {Array} urls 请求的url列表
 * @param {Number} maxNum 最大并发数
 * @returns
 */
function sendPostRequestInParallel(urls, maxNum) {
  // 如果 urls 为空,直接返回一个空数组
  if (urls.length === 0) {
    return Promise.resolve([]);
  }

  // 结果为成功的,如果请求失败的话,把失败原因放数组中即可
  return new Promise((resolve) => {
    let index = 0; // 要处理的下一条 url 索引
    const results = []; // 存放请求结果

    async function _request() {
      const url = urls[index];
      // 用变量保存下当前索引
      const i = index;
      index++;

      try {
        // 发送请求,并且吧结果放入对应为止
        const res = await fetch(url);
        results[i] = await res.json();
      } catch (err) {
        // 失败的话,就把失败原因加进去,这里不能使用push,不然结果顺序和参数地址顺序不一致
        results[i](err);
      }

      console.log(results);
    }

    // 这里现调用3次测试
    _request();
    _request();
    _request();
  });
}

const urls = [];
for (let i = 1; i <= 10; i++) {
  urls.push(`http://localhost:8888/testTcc?num=${i}`);
}

// 10个url,每次3个并发
sendPostRequestInParallel(urls, 3);

我们把网速调慢,进行测试

在这里插入图片描述

3、递归处理

  • 当一条处理完以后,要从数组中再拿出来一条执行,直到执行完最后一条
/**
 *
 * @param {Array} urls 请求的url列表
 * @param {Number} maxNum 最大并发数
 * @returns
 */
function sendPostRequestInParallel(urls, maxNum) {
  // 如果 urls 为空,直接返回一个空数组
  if (urls.length === 0) {
    return Promise.resolve([]);
  }

  // 结果为成功的,如果请求失败的话,把失败原因放数组中即可
  return new Promise((resolve) => {
    let index = 0; // 要处理的下一条 url 索引
    const results = []; // 存放请求结果

    async function _request() {
      const url = urls[index];
      // 用变量保存下当前索引
      const i = index;
      index++;

      try {
        // 发送请求,并且吧结果放入对应为止
        const res = await fetch(url);
        results[i] = await res.json();
      } catch (err) {
        // 失败的话,就把失败原因加进去,这里不能使用push,不然结果顺序和参数地址顺序不一致
        results[i](err);
      } finally {
        // 如果一条执行完,则继续拿出来下一条执行,直到urls执行完
        if (index < urls.length) {
          _request();
        }
      }

      console.log(results);
    }

    // 这里现调用3次测试
    _request();
    _request();
    _request();
  });
}

const urls = [];
for (let i = 1; i <= 10; i++) {
  urls.push(`http://localhost:8888/testTcc?num=${i}`);
}

// 10个url,每次3个并发
sendPostRequestInParallel(urls, 3);

在这里插入图片描述

4、处理限制并发数

  • 上面我们手动执行了三次,要改成循环 参数中的并发数
/**
 *
 * @param {Array} urls 请求的url列表
 * @param {Number} maxNum 最大并发数
 * @returns
 */
function sendPostRequestInParallel(urls, maxNum) {
  // 如果 urls 为空,直接返回一个空数组
  if (urls.length === 0) {
    return Promise.resolve([]);
  }

  // 结果为成功的,如果请求失败的话,把失败原因放数组中即可
  return new Promise((resolve) => {
    let index = 0; // 要处理的下一条 url 索引
    const results = []; // 存放请求结果

    async function _request() {
      const url = urls[index];
      // 用变量保存下当前索引
      const i = index;
      index++;

      try {
        // 发送请求,并且吧结果放入对应为止
        const res = await fetch(url);
        results[i] = await res.json();
      } catch (err) {
        // 失败的话,就把失败原因加进去,这里不能使用push,不然结果顺序和参数地址顺序不一致
        results[i](err);
      } finally {
        // 如果一条执行完,则继续拿出来下一条执行,直到urls执行完
        if (index < urls.length) {
          _request();
        }
      }

      console.log(results);
    }

    // 这里取 最小值,防止urls长度小于maxNum
    for (let i = 0; i < Math.min(urls.length, maxNum); i++) {
      _request();
    }
  });
}

const urls = [];
for (let i = 1; i <= 10; i++) {
  urls.push(`http://localhost:8888/testTcc?num=${i}`);
}

// 10个url,每次3个并发
sendPostRequestInParallel(urls, 3);

在这里插入图片描述

5、处理函数返回值

  • 接口请求有快有慢,最后一个接口请求完,有可能结果还没返回完,所以并不是返回值的时候,那么我们就要等所有的接口都请求完成才可以返回,这里定义一个变量count,每一个请求返回结果后再++,直到 count==urls.length
/**
 *
 * @param {Array} urls 请求的url列表
 * @param {Number} maxNum 最大并发数
 * @returns
 */
function sendPostRequestInParallel(urls, maxNum) {
  // 如果 urls 为空,直接返回一个空数组
  if (urls.length === 0) {
    return Promise.resolve([]);
  }

  // 结果为成功的,如果请求失败的话,把失败原因放数组中即可
  return new Promise((resolve) => {
    let index = 0; // 要处理的下一条 url 索引
    const results = []; // 存放请求结果
    let count = 0; // 记录已经完成的请求个数

    async function _request() {
      const url = urls[index];
      // 用变量保存下当前索引
      const i = index;
      index++;

      try {
        // 发送请求,并且吧结果放入对应为止
        const res = await fetch(url);
        results[i] = await res.json();
      } catch (err) {
        // 失败的话,就把失败原因加进去,这里不能使用push,不然结果顺序和参数地址顺序不一致
        results[i](err);
      } finally {
        // 如果一条执行完,则继续拿出来下一条执行,直到urls执行完
        if (index < urls.length) {
          _request();
        }

        count++;

        if (count === urls.length) {
          resolve(results);
        }
      }
    }

    // 这里取 最小值,防止urls长度小于maxNum
    for (let i = 0; i < Math.min(urls.length, maxNum); i++) {
      _request();
    }
  });
}

const urls = [];
for (let i = 1; i <= 10; i++) {
  urls.push(`http://localhost:8888/testTcc?num=${i}`);
}

// 10个url,每次3个并发
sendPostRequestInParallel(urls, 3).then((res) => {
  console.log(res);
});

在这里插入图片描述

6、结束

  • 至此,我们所有问题都已经解决了,下面是全部代码,
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    /**
     *
     * @param {Array} urls 请求的url列表
     * @param {Number} maxNum 最大并发数
     * @returns
     */
    function sendPostRequestInParallel(urls, maxNum) {
      // 如果 urls 为空,直接返回一个空数组
      if (urls.length === 0) {
        return Promise.resolve([]);
      }

      // 结果为成功的,如果请求失败的话,把失败原因放数组中即可
      return new Promise((resolve) => {
        let index = 0; // 要处理的下一条 url 索引
        const results = []; // 存放请求结果
        let count = 0; // 记录已经完成的请求个数

        async function _request() {
          const url = urls[index];
          // 用变量保存下当前索引
          const i = index;
          index++;

          try {
            // 发送请求,并且吧结果放入对应为止
            const res = await fetch(url);
            results[i] = await res.json();
          } catch (err) {
            // 失败的话,就把失败原因加进去,这里不能使用push,不然结果顺序和参数地址顺序不一致
            results[i](err);
          } finally {
            // 如果一条执行完,则继续拿出来下一条执行,直到urls执行完
            if (index < urls.length) {
              _request();
            }

            count++;

            if (count === urls.length) {
              resolve(results);
            }
          }
        }

        // 这里取 最小值,防止urls长度小于maxNum
        for (let i = 0; i < Math.min(urls.length, maxNum); i++) {
          _request();
        }
      });
    }

    const urls = [];
    for (let i = 1; i <= 10; i++) {
      urls.push(`http://localhost:8888/testTcc?num=${i}`);
    }

    // 10个url,每次3个并发
    sendPostRequestInParallel(urls, 3).then((res) => {
      console.log(res);
    });
  </script>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/924350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ7:消息转换器

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

螺旋矩阵(java)

题目描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 代码思路&#xff1a; class Solution {public List<Integer> spiralOrder(int[][] matrix) {List<Integer> list new ArrayList<>(); …

Jenkins的使用

文章目录 一、Jenkins是什么\有什么用\与GitLab的对比二、Jenkins的安装与配置Jenkins的安装方式在Linux上安装Jenkins&#xff1a;在Windows上安装Jenkins&#xff1a;配置Jenkins&#xff1a; &#xff08;可选&#xff09;配置启动用户为root&#xff08;一定要是root吗??…

[在线实验]-ActiveMQ Docker镜像的下载与部署

镜像下载 下载ActiveMQ的Docker镜像文件。通常&#xff0c;这些文件会以.tar格式提供&#xff0c;例如activemq.tar。 docker的activemq镜像资源-CSDN文库 加载镜像 下载完成后&#xff0c;您可以使用以下命令将镜像文件加载到Docker中&#xff1a; docker load --input a…

【AI绘画】Midjourney进阶:色调详解(下)

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;Midjourney中的色彩控制为什么要控制色彩&#xff1f;为什么要在Midjourney中控制色彩&#xff1f; &#x1f4af;色调纯色调灰色调暗色调 &#x1f4af…

YOLO系列论文综述(从YOLOv1到YOLOv11)【第3篇:YOLOv1——YOLO的开山之作】

YOLOv1 1 摘要2 YOLO: You Only Look Once2.1 如何工作2.2 网络架构2.3 训练2.4 优缺点 YOLO系列博文&#xff1a; 【第1篇&#xff1a;概述物体检测算法发展史、YOLO应用领域、评价指标和NMS】【第2篇&#xff1a;YOLO系列论文、代码和主要优缺点汇总】 ——————————…

数字图像处理(9):VGA接口及其时序

&#xff08;1&#xff09;特点&#xff1a;成本低、结构简单、应用灵活 VGA接口需要五个信号&#xff1a;R、G、B、Hsync、Vsync &#xff08;2&#xff09;VGA的工作原理&#xff1a; 设定一个高速时钟信号&#xff08;像素时钟&#xff09;来控制每个像素的传输速率&#…

微信小程序按字母顺序渲染城市 功能实现详细讲解

在微信小程序功能搭建中&#xff0c;按字母渲染城市会用到多个ES6的方法&#xff0c;如reduce&#xff0c;map&#xff0c;Object.entries()&#xff0c;Object.keys() &#xff0c;需要组合熟练掌握&#xff0c;才能优雅的处理数据完成渲染。 目录 一、数据分析 二、数据处理 …

DVWA靶场通过——文件上传漏洞

File Upload漏洞 它允许攻击者通过上传恶意文件来执行任意代码、窃取数据、获取服务器权限&#xff0c;甚至完全控制服务器。为了防止文件上传漏洞&#xff0c;开发者需要对文件上传过程进行严格的验证和处理。 1. 文件上传漏洞概述 文件上传漏洞发生在Web应用程序允许用户通过…

react后台管理系统(一)

&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容:react后台管理系统(一) 前言 本文档详细介绍了如何从零开始搭建一个基于 React 和 Ant Design 的…

Vue.js --- 生命周期

1. 前言 在 Vue.js 中&#xff0c;生命周期是指一个 Vue 实例从创建到销毁的过程。Vue 提供了一系列的生命周期钩子&#xff08;lifecycle hooks&#xff09;&#xff0c;让开发者可以在不同的阶段执行特定的代码。了解这些生命周期钩子是构建 Vue 组件的基础&#xff0c;能够…

使用1panel一键安装Ollama WebUI连接本地Ollama使用开源ai模型

当前我的环境 设备有限只有一张3060 12gb显卡&#xff0c;平时用来轻度学习 主机&#xff1a;windows server Ollama&#xff1a;windows版&#xff08;它也有linux和mac&#xff09; 因虚拟机使用的服务器无显卡&#xff0c;只用来跑面板和WebUi 虚拟机&#xff1a;ubuntu se…

任意文件读取漏洞(CVE-2024-7928)修复

验证CVE-2024-7928问题是否存在可以使用如下方法&#xff1a; https://域名/index/ajax/lang?lang..//..//目录名/文件名&#xff08;不带后缀&#xff09; 目录名是该项目的一个目录&#xff0c;这里目录位置为nginx设置站点目录为基准&#xff0c;网上两层目录。 文件名…

房屋出租出售预约系统支持微信小程序+H5+APP

核心功能有&#xff1a;新盘销售、房屋租赁、地图找房、小区找房&#xff0c;地铁找房等方式。 地图找房&#xff1a;通过地图标注查看附近房源&#xff0c;方便用户根据地理位置查找合适的房产。二手房资讯&#xff1a;提供租房及二手房市场的相关资讯&#xff0c;帮助用户了…

设计模式:11、迭代器模式(游标)

目录 0、定义 1、迭代器模式的四种角色 2、迭代器模式的UML类图 3、示例代码 4、迭代器的next()方法与集合的get(int index)方法的效率对比&#xff08;LinkedList为例&#xff09; 0、定义 提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而又不需要暴露该对象…

抓SystemTrace的简易方法

前言&#xff1a; Systrace是分析Android性能问题的神器。一般抓trace命令是需要在AndroidSDK下的\platform-tools\systrace执行\systrace.py&#xff0c;很奇怪我的AndroidSDK并没有systrace文件夹&#xff0c;于是CSDN单独下载了trace文件 但是我一运行.\systrace.py -b 102…

微信小程序 城市点击后跳转 并首页显示被点击城市

在微信小程序中&#xff0c;渲染出城市列表后&#xff0c;如何点击城市&#xff0c;就跳转回到首页&#xff0c;并在首页显示所点击的城市呢&#xff1f; 目录 一、定义点击城市的事件 二、首页的处理 首页&#xff1a;点击成都市会跳转到城市列表 城市列表&#xff1a;点击…

修改IDEA配置导致Spring Boot项目读取application.properties中文乱码问题

之前很多配置都是放在nacos里面&#xff0c;然后这次同事有个配置写在application.properties中&#xff0c;这个配置含有中文&#xff0c;启动之后发现拿到的中文值会乱码&#xff0c;然后就帮忙看了一下问题。 排查问题 经过不停的百度、排查发现&#xff0c;spring读取app…

STM32F103系列单片机通用和复用I/O(GPIO)

一、GPIO功能描述 每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL&#xff0c; GPIOx_CRH)&#xff0c;两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR)&#xff0c;一个32位置位/复位寄存器(GPIOx_BSRR)&#xff0c;一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。…

从 App Search 到 Elasticsearch — 挖掘搜索的未来

作者&#xff1a;来自 Elastic Nick Chow App Search 将在 9.0 版本中停用&#xff0c;但 Elasticsearch 拥有你构建强大的 AI 搜索体验所需的一切。以下是你需要了解的内容。 生成式人工智能的最新进展正在改变用户行为&#xff0c;激励开发人员创造更具活力、更直观、更引人入…