前端 vue单页面中请求数量过多问题 控制单页面请求并发数
需求背景:
页面中需要展示柜子,一个柜子需要调用 详情接口以及状态接口
也就是说有一个柜子就需要调用两个接口,在项目初期,接手的公司项目大概也就4-5个柜子,最多的也不超过10个,但是突然进来一个项目,这个项目中有 TM 300多台柜子,所以第一次渲染的时候,同时向服务器请求了600多个接口,导致接口超时,服务也挂了,主要也没想到会存在这种情况,咱也没遇到过啊,ok,既然问题来了,咱就解决问题
我一开始的代码逻辑就是先获取机柜数量,然后循环这个数组,在循环体中调用接口,不过我是通过添加到promise数组中,然后统一处理的,上代码
const getCabinetNum = async (id) => {let cabinetList = await cabinetApi.getCabinetList({projectId: id ? id : projectId.value})const promises = cabinetList?.map(async (cabinet) => {const data = await cabinetApi.getCabinetLive({cabinetId: cabinet.instanceUid,projectId: cabinet.projectId})const status = await cabinetApi.getCabinetStatus({cabinetId: cabinet.instanceUid,projectId: cabinet.projectId})return {...data, ...status}})if (promises && promises.length > 0) {const results = await Promise.all(promises)cabinetData.value = results}}
cabinetData.value 就是我最后渲染柜子的数据
这段代码的问题有两个:
1. 如果cabinetList 的长度过长 比如20个,我就要同时请求40个接口
2. 我在完全获取 cabinetData 之前,柜子是渲染不出来的,因为我封装的柜子组件是需要循环 cabinetData 去渲染的
那么,先来解决第一个问题,如何控制请求并发数量
思路:将 cabinetList 进行分割成组,控制每组的个数,然后通过组的形式向后端发送请求
const fetchCabinetDetailsInBatches = async (cabinetList, batchSize) => {// 计算需要分成的批次数量const batches = Math.ceil(cabinetList.length / batchSize)// 用于存储所有机柜详情的数组const allCabinetData = []// 循环每个批次for (let i = 0; i < batches; i++) {// 获取当前批次的起始索引和结束索引const startIndex = i * batchSizeconst endIndex = Math.min((i + 1) * batchSize, cabinetList.length)// 获取当前批次的机柜列表const batchCabinets = cabinetList.slice(startIndex, endIndex)// 定义一个数组,用于存储当前批次的所有 getCabinetLive 方法返回的 Promise 对象const promiseList = []// 循环遍历当前批次的机柜列表,为每个机柜调用 getCabinetLive,getCabinetStatus 方法,并将返回的 Promise 对象存储到 promiseList 中batchCabinets.forEach((cabinet) => {promiseList.push(Promise.all([cabinetApi.getCabinetLive({cabinetId: cabinet.instanceUid,projectId: cabinet.projectId}),cabinetApi.getCabinetStatus({cabinetId: cabinet.instanceUid,projectId: cabinet.projectId})]))})// 使用 Promise.all() 并行处理当前批次的所有 Promise 对象const batchResults = await Promise.all(promiseList)// 将当前批次的机柜数据存入 allCabinetData 数组中batchResults.forEach(([cabinetInfoList, status], index) => {allCabinetData[startIndex + index] = {...cabinetInfoList, status}})}return allCabinetData
}
这个函数是用来做分组以及处理数据的
使用如下
const getCabinetNum = async (id) => {let cabinetList = await cabinetApi.getCabinetList({projectId: id ? id : projectId.value})cabinetData.value = await fetchCabinetDetailsInBatches(cabinetList, 3)
}
其实主要还是利用promise.all 方法,分批处理每组的多个请求
2.下面解决第二个问题,如何能在完全获取到 cabinetData 之前渲染出柜子,并且,伴随着接口的请求,接着渲染呢
上面我提到了我是通过将 cabinetData 传递给子组件的,那么我只需要要监听 cabinetData 的变化,不断更新 cabinetData 不就好了,我首先想到的是 computed
const renderedCabinets = computed(() => {return cabinetData.value
})
通过不断变化的 cabinetData.value 将 renderedCabinets传递给子组件
但是上面的代码存在的问题就是 cabinetData.value还是需要等待全部获取,所以只要稍作修改即可
const fetchCabinetDetailsInBatches = async (cabinetList, batchSize) => {// 计算需要分成的批次数量const batches = Math.ceil(cabinetList.length / batchSize)// 用于存储所有机柜详情的数组const allCabinetData = []// 循环每个批次for (let i = 0; i < batches; i++) {// 获取当前批次的起始索引和结束索引const startIndex = i * batchSizeconst endIndex = Math.min((i + 1) * batchSize, cabinetList.length)// 获取当前批次的机柜列表const batchCabinets = cabinetList.slice(startIndex, endIndex)// 定义一个数组,用于存储当前批次的所有 getCabinetLive 方法返回的 Promise 对象const promiseList = []// 循环遍历当前批次的机柜列表,为每个机柜调用 getCabinetLive,getCabinetStatus 方法,并将返回的 Promise 对象存储到 promiseList 中batchCabinets.forEach((cabinet) => {promiseList.push(Promise.all([cabinetApi.getCabinetLive({cabinetId: cabinet.instanceUid,projectId: cabinet.projectId}),cabinetApi.getCabinetStatus({cabinetId: cabinet.instanceUid,projectId: cabinet.projectId})]))})// 使用 Promise.all() 并行处理当前批次的所有 Promise 对象const batchResults = await Promise.all(promiseList)// 将当前批次的机柜数据存入 allCabinetData 数组中batchResults.forEach(([cabinetInfoList, status], index) => {allCabinetData[startIndex + index] = {...cabinetInfoList, status}})//这里!!!!!!!!!!!!!!!!!cabinetData.value = [...allCabinetData]}return allCabinetData
}
我在每次循环之后 将 cabinetData.value 赋值为最新获取的数据,这样每次循环,cabinetData.value就会改变,从而 renderedCabinets 也会改变
ok 这样就大功告成了
这段代码其实还有一个问题就是如果在接口没有请求完之前,你离开了当前页面,会导致在别的页面下,没请求完的接口依然在请求,会导致内存泄漏,就跟组件销毁前没销毁定时器是一个道理
可以利用axios的关闭请求的方法来解决,后续会更新代码
其实这个问题还有一种更简单高效的解决方案,就是懒加载,在用户滑动查看到新的柜子之前,不请求,滑动到未加载的机柜就请求接口,跟图片懒加载一个道理,这个方案更加简单明了,而且性能肯定比目前这个方案好,后续我也会试一下这个方案
相关文章:
前端 vue单页面中请求数量过多问题 控制单页面请求并发数
需求背景: 页面中需要展示柜子,一个柜子需要调用 详情接口以及状态接口 也就是说有一个柜子就需要调用两个接口,在项目初期,接手的公司项目大概也就4-5个柜子,最多的也不超过10个,但是突然进来一个项目&a…...

HarmonyOS开发实例:【分布式手写板】
介绍 本篇Codelab使用设备管理及分布式键值数据库能力,实现多设备之间手写板应用拉起及同步书写内容的功能。操作流程: 设备连接同一无线网络,安装分布式手写板应用。进入应用,点击允许使用多设备协同,点击主页上查询…...

Unity TMP Inputfield 输入框 框选 富文本 获取真实定位
一、带富文本标签的框选是什么 UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition,开始选择时的光标下标和当前光标下标 对于未添加富文本标签时,直接通过以上两个值,判断一下框选方向(前向后/后向前&…...

如何在原生项目中集成flutter
两个前提条件: 从flutter v1.17版本开始,flutter module仅支持AndroidX的应用在release模式下flutter仅支持一下架构:x84_64、armeabi-v7a、arm6f4-v8a,不支持mips和x86;所以引入flutter前需要在app/build.gradle下配置flutter支持的架构 a…...

【设计模式】策略模式
目录 什么是策略模式 代码实现 什么是策略模式 策略模式是一种行为型设计模式,它定义了一系列算法,将每个算法封装成一个独立的对象,使得它们可以相互替换。 在策略模式中,通常有三个角色: 环境类(Cont…...

Java面试八股之Iterator和ListIterator的区别是什么
Iterator和ListIterator的区别是什么 这道题也是考查我们对迭代器相关的接口的了解程度,从代码中我们可以看出后者是前者的子接口,在此基础上做了一些增强,并且只用于List集合类型。 定义与基本概念 Iterator: 定义:…...

服务器中毒怎么办?企业数据安全需重视
互联网企业: 广义的互联网企业是指以计算机网络技术为基础,利用网络平台提供服务并因此获得收入的企业。广义的互联网企业可以分为:基础层互联网企业、服务层互联网企业、终端层互联网企业。 狭义的互联网企业是指在互联网上注册域名,建立网…...

k8s使用harbor私有仓库镜像 —— 筑梦之路
官方文档: Secret | Kubernetes ImagePullSecrets的设置是kubernetes机制的另一亮点,习惯于直接使用Docker Pull来拉取公共镜像,但非所有容器镜像都是公开的。此外,并不是所有的镜像仓库都允许匿名拉取,也就是说需要身份认证&…...

tcp bbr pacing 的对与错
前面提到 pacing 替代 burst 是大势所趋,核心原因就是摩尔定律逐渐失效,主机带宽追平交换带宽,交换机不再能轻易吸收掉主机突发,且随着视频类流量激增,又不能以大 buffer 做带宽后备。因此,主机必须 pacing…...
MySQL学习-非事务相关的六大日志、InnoDB的三大特性以及主从复制架构
一. 六大日志 慢查询日志:记录所有执行时间超过long_query_time的查询,方便定位并优化。 # 查询当前慢查询日志状态 SHOW VARIABLES LIKE slow_query_log; #启用慢查询日志 SET GLOBAL slow_query_log ON; #设置慢查询文件位置 SET GLOBAL slow_query_log_file …...

【软件测试】MIL/HIL/PIL/SIL测试
V字型开发流程 引用文章:汽车行业V模型开发详解 V模型开发(V-Model Development)是一种广泛应用于汽车行业的系统开发方法。它以字母“V”形状的图表形式展示了开发过程中不同阶段之间的关系,从需求分析到系统整合和验证&#x…...
WebKit结构深度解析:打造高效与安全的浏览器引擎
WebKit结构深度解析:打造高效与安全的浏览器引擎 在现代网络世界中,浏览器作为连接用户与互联网信息的桥梁,其背后的技术架构至关重要。WebKit,作为当今最流行的开源浏览器引擎之一,其结构设计和功能实现对于提升浏览…...
SQLSERVER对等发布问题处理
问题1: 无法对 数据库Sast_Business 执行 删除,因为它正用于复制。 (.Net SqlClient Data Provider) 处理: USE [master]; GO EXEC sp_replicationdboption dbname NSast_Business, optname Npublish, value Nfalse; EXEC sp_replica…...
CentOS 7 中时间快了 8 小时
1.查看系统时间 1.1 timeZone显示时区 [adminlocalhost ~]$ timedatectlLocal time: Mon 2024-04-15 18:09:19 PDTUniversal time: Tue 2024-04-16 01:09:19 UTCRTC time: Tue 2024-04-16 01:09:19Time zone: America/Los_Angeles (PDT, -0700)NTP enabled: yes NTP synchro…...

itext7 pdf转图片
https://github.com/thombrink/itext7.pdfimage 新建asp.net core8项目,安装itext7和system.drawing.common 引入itext.pdfimage核心代码 imageListener下有一段不安全的代码 unsafe{for (int y 0; y < image.Height; y){byte* ptrMask (byte*)bitsMask.Scan…...
搜维尔科技:Manus Xsens Metagloves新一代手指捕捉
Manus Xsens Metagloves新一代手指捕捉 搜维尔科技:Manus Xsens Metagloves新一代手指捕捉...
Python与Redis:提升性能,确保可靠性,掌握最佳实践
在 Python 中,有多个库可用于与 Redis 数据库进行交互,其中最受欢迎的是 redis-py。这是一个 Python 客户端库,提供了与 Redis 数据库进行通信的丰富功能。 Python操作Redis操作步骤 安装 redis-py 使用 pip 安装 redis-py: p…...

GPT国内能用吗
2022年11月,Open AI发布ChatGPT,ChatGPT展现了大型语模型在自然语言处理方面的惊人进步,其生成文本的流畅度和连贯性令人印象深刻,为AI应用打开了新的可能性。 ChatGPT的出现推动了AI技术在各个领域的应用,例如&#x…...

中科亿海微-CL1656功能验证开发板
I. 引言 A. 研究背景与意义 CL1656是一款精度高、功耗低、成本低的5V单片低功耗运放,由核心互联公司研发制造,CL1656 是一个 16-bit、快速、低功耗逐次逼近型 ADC,吞吐速率高达 250 kSPS,并且内置低噪声、宽 带宽采样保持放大器。…...

学习STM32第十五天
SPI外设 一、简介 STM32F4XX内部集成硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU负担,可配置8位/16位数据帧,高位(最常用)/低位先行,三组SPI接口,支持DMA…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...