当前位置: 首页 > news >正文

前端实现【 批量任务调度管理器 】demo优化

一、前提介绍

我在前文实现过一个【批量任务调度管理器】的 demo,能实现简单的任务批量并发分组,过滤等操作。但是还有很多优化空间,所以查找一些优化的库,
主要想优化两个方面, 上篇提到的:

针对 3,其实可以自己手写一个,也可以依靠 如什么来实现。
针对 2,最难的是根据【当前系统负载或网络状况调整并发请求数量】,这必须需要引入一个检测系统的东西。

而动态调整数量,我现在的代码其实已经可以满足,我只是无法【获取当前系统负载或网络状况】。
当然我搜了一些,也有推荐 P-Queue 这类队列库来现在我现在的功能的,它有一些优点,比如:动态调整并发数、任务优先级、延迟、减少手动实现的复杂性,简化代码逻辑,提高可读性和维护性等等。

最后实现功能:基于 P-Queue 和 AbortController 的批量操作功能,其中包括了动态并发控制、网络状态监测和请求取消功能。

二、P-Queue 介绍

P-Queue 是一个基于 Promise 的优先队列,它允许你控制并发任务的数量,并且可以设置任务的优先级。P-Queue 的使用非常简单,只需要创建一个队列实例,然后使用 add 方法添加任务即可。

优点:

1. 固定并发数: 创建 P-Queue 实例时指定一个并发数,例如 5。这表示队列最多同时处理 5 个任务。
2. 自动调度:只需要将任务添加到队列中,而不需要关心任务的调度和执行顺序。P-Queue 会根据你指定的并发数自动处理任务——我现在自己手写的那个只是考虑使用 for 循环启动多个并发请求,并通过递归调用来处理下一任务。这种方法不涉及任务队列的概念,而是直接处理任务并发
3. 任务执行:任务被添加到队列时,P-Queue 会立即检查当前的并发任务数量。如果当前执行的任务数少于并发数限制,它会立即开始执行新的任务。
如果当前正在执行的任务数达到并发限制,P-Queue 会将新任务放入队列中,等待直到有空闲的并发槽位(即当前正在运行的任务数减少到低于并发限制)。
4. 任务完成:当一个任务完成时,P-Queue 会检查队列中的其他待处理任务。如果有任务在队列中等待并且当前并发数仍然未达到限制,它会自动开始执行下一个任务。

使用案例:

import PQueue from 'p-queue'
import axios from 'axios'// 创建一个队列,设置并发数为 5
const queue = new PQueue({ concurrency: 5 })const tasks = [() => axios.get('/api/task1'),() => axios.get('/api/task2')// 更多任务...
]// 添加任务到队列中
tasks.forEach((task) => {queue.add(task)
})// 动态调整并发数——可以根据系统的情况来调整
setTimeout(() => {queue.concurrency = 10 // 动态调整并发数
}, 5000)// 等待所有任务完成
queue.onIdle().then(() => {console.log('All tasks completed')
})

三、动态检测的实现

我曾想过使用一些第三方库来实现检测当前系统的情况,然后动态控制并发数量,这样会更友好,查了一些方案,感觉没有必要。

实际的负载检测逻辑通常依赖于系统性能指标和资源使用情况。一些常见的负载检测方法和第三方库:

  1. os-utils:提供系统负载和资源使用情况的简单接口。
  2. systeminformation:提供详细的系统信息,包括 CPU、内存、网络等。
  3. node-os-utils:获取系统的 CPU、内存、磁盘和网络信息,适合用于 Node.js 环境。

对于大多数应用,特别是当任务负载和并发需求相对稳定时,动态调整可能显得过于复杂。遂放弃。

四、优化效果

最后,我的方案如下:
基于 P-Queue 和 AbortController 的批量操作功能,其中包括了动态并发控制、网络状态监测和请求取消功能。以下是实现功能的详细描述:

功能优化概述

  1. 动态并发控制:getConcurrency:根据设备的硬件线程数(CPU 核心数)动态计算并发请求数量,一个比较基础的检测,也可以考虑其他的检查
  2. 队列 queue:使用 P-Queue 创建任务队列,初始化并发数量。
  3. 监听网络是否中断,再批量请求处理:每个请求的处理函数,使用 AbortController 允许在网络断开时中断请求。
  4. 注意:组件挂载时初始化网络状态监听、也可以考虑监听网络的情况更新 P-Queue 的并发数量

优点是:可扩展性强,还是比较简单灵活,结合了并发控制、请求取消和网络状态检测。能够提升性能,优化用户体验。

代码实现

import PQueue from 'p-queue'
import axios from 'axios'onMounted(() => {window.addEventListener('online', handleNetworkChange)window.addEventListener('offline', handleNetworkChange)
})
// 创建 AbortController 实例
let abortController = new AbortController()// 网络状态检测函数
const isOnline = () => navigator.onLine
// 定义动态并发控制函数(根据需要自定义)
const getConcurrency = () => {//目的是根据系统的硬件资源或其他条件动态调整并发请求的数量。具体来说,它通过 navigator.hardwareConcurrency 获取设备的硬件线程数(CPU核心数),然后将其限制在一个合适的范围内(在这个例子中是 1 到 10)// 你可以根据系统负载、网络状况等动态调整并发数return Math.max(1, Math.min(10, navigator.hardwareConcurrency || 4))
}// 创建 P-Queue 实例
const queue = new PQueue({ concurrency: getConcurrency() })// 更新并发数的函数
const updateConcurrency = () => {queue.concurrency = getConcurrency()
}
// 存储每个请求的 AbortController 实例
const controllers = ref([])
const batchOperation = (title, operationType, axiosConfig, shouldFilterList) => {const successCount = ref(0)const errorCount = ref(0)// 执行批量操作startLoading()const requestTaskList = shouldFilterList? tableData.value.filter((item, index, arr) => arr.findIndex((val) => val.id === item.id) === index): tableData.valueif (requestTaskList.length === 0) {ElMessage.error('没有可操作的任务!')stopLoading()return}// 定义请求函数const requestFunction = async (row) => {// 创建新的 AbortController 实例const controller = new AbortController()controllers.value.push(controller) // 将控制器添加到集合中const params = {}try {const res = await axios.request({url: axiosConfig.url,method: axiosConfig.method,params: params,signal: abortController.signal // 使用 AbortController 实例})if (res.data.code === 200) {successCount.value++} else {errorCount.value++}} catch (error) {if (error.name === 'AbortError') {console.warn('Request was aborted due to network being offline.')} else {errorCount.value++console.error('Request failed:', error)}}}requestTaskList.forEach((row) => {queue.add(() => requestFunction(row))})queue.onIdle().then(() => {stopLoading(tabs)ElNotification({title: `${title}结果`,message: `${requestTaskList.length} 个任务,${successCount.value} 个处理成功,${errorCount.value} 个处理失败。`,type: errorCount.value === 0 ? 'success' : 'warning'})controllers.value = [] // 清空控制器集合})// 动态调整并发数的定时器(每隔 5 分钟更新一次)——感觉作用不大,会导致不必要的性能开销// setInterval(() => {//   queue.concurrency = getConcurrency()// }, 300000)
}
// 取消所有请求
const cancelAllRequests = () => {controllers.value.forEach((controller) => {controller.abort()})controllers.value = [] // 清空控制器集合
}
// 监听网络状态变化
const handleNetworkChange = () => {if (!isOnline()) {console.log('Network is offline. Cancelling ongoing requests.')cancelAllRequests() // 取消所有请求} else {console.log('Network is back online. Resuming requests.')abortController = new AbortController() // 创建新的 AbortController 实例}
}// 在组件卸载之前,取消所有未完成的请求
onBeforeUnmount(() => {isUnmount.value = truewindow.removeEventListener('online', handleNetworkChange)window.removeEventListener('offline', handleNetworkChange)cancelAllRequests() // 组件卸载时取消所有请求
})

效果评价

1.并发数测试

同样 20 条,优化前:
在这里插入图片描述

优化第一版,上篇:
在这里插入图片描述

优化第二版,这版:
在这里插入图片描述

其实吧,我也看不出来,性能有啥变化,累了,还是太少了吧……
但是,代码友好了一些些吧,并发上来讲,比之前好很多。

2.取消请求测试

同样 20 条,优化前,没有加取消的功能,断网会——500!如果你的 axios 拦截里对 500 进行处理的话,就会误伤。

优化后:
断网前发送的请求会 500,但是断网后,有一些请求还未发出去,所以会被取消。
在这里插入图片描述
效果好一点点。

五、总结

对上面的功能主要做了队列并发处理,简单的动态检测系统网络是否连接然后中断请求的处理,算是优化了该 demo。以后如果接触到更好的办法会继续更新!

相关文章:

前端实现【 批量任务调度管理器 】demo优化

一、前提介绍 我在前文实现过一个【批量任务调度管理器】的 demo,能实现简单的任务批量并发分组,过滤等操作。但是还有很多优化空间,所以查找一些优化的库, 主要想优化两个方面, 上篇提到的: 针对 3&…...

【数据结构】包装类和泛型

🎉欢迎大家收看,请多多支持🌹 🥰关注小哇,和我一起成长🚀个人主页🚀 ⭐在更专栏Java ⭐数据结构 ⭐已更专栏有C语言、计算机网络⭐ 👑目录 包装类🌙 ⭐基本类型对应的包…...

浅学爬虫-数据存储

在数据爬取完成后,我们需要将数据存储起来,以便于后续的分析和处理。常见的数据存储方式包括存储到CSV文件和存储到数据库。下面我们详细介绍如何实现这些存储方式。 存储到CSV CSV(Comma-Separated Values)文件是一种常用的文本…...

十六、maven git-快速上手(智慧云教育平台)

🌻🌻 目录 一、概述及项目管理工具介绍1.1 项目介绍1.2 maven 介绍及其配置1.2.1 maven 介绍1.2.2 maven 下载与配置 1.3 pom 中常见标签的使用1.4 后端项目环境的搭建1.5 Git 简介1.6 Git 的基本使用1.6.1 码云的注册与仓库创建1.6.2 上传代码到码云仓库…...

chrome/edge浏览器插件开发入门与加载使用

同学们可以私信我加入学习群! 正文开始 前言一、插件与普通前端项目二、开发插件——manifest.json三、插件使用edge浏览器中使用/加载插件chrome浏览器中使用/加载插件 总结 前言 chrome插件的出现,初衷可能是为了方便用户更好地控制浏览器&#xff0c…...

【完美解决】 TypeError: ‘str’ object does not support item assignment

【完美解决】 TypeError: ‘str’ object does not support item assignment 在Python编程中,遇到TypeError: str object does not support item assignment这样的错误通常意味着你试图修改字符串中的某个字符,但字符串是不可变类型,不支持这…...

Android SurfaceFlinger——渲染开始帧(四十三)

通过前面的文章我们介绍了 SurfaceFlinger 图层合成的整体流程,已经对应步骤的前五步,这里我们开始介绍帧渲染流程的第一步——开始帧。 1.更新输出设备的色彩配置文件2.更新与合成相关的状态3.计划合成帧图层4.写入合成状态5.设置颜色矩阵6.开始帧7.准备帧数据以进行显示(异…...

fastadmin搜索栏实现某字段动态下拉搜索

记录:fastadmin搜索栏实现某字段动态下拉搜索 方式一:使用selectpicker组件,可多选 { field: travel_agency, title:__(Travel_agency),addClass:"selectpicker", operate:"IN",data:"multiple", searchList:…...

.NET未来路在何方?

简述 在软件开发的漫长旅程中,将代码打包成可执行的EXE文件是一项必不可少的技能。它不仅能够保护源代码,还能为用户提供便捷的安装体验。但手动打包过程繁琐且容易出错,自动化打包成为了开发者的福音。 在软件开发的浩瀚星空中,.…...

Vue开发环境搭建

文章目录 引言I 安装NVM1.1 Windows系统安装NVM,实现Node.js多版本管理1.2 配置下载镜像1.3 NVM常用操作命令II VUE项目的基础配置2.1 制定不同的环境配置2.2 正式环境隐藏日志2.3 vscode常用插件引言 开发工具: node.js 、npm 开发编辑器:vscode 开发框架:VUE I 安装NVM…...

【数据结构初阶】详解:实现循环队列、用栈实现队列、用队列实现栈

文章目录 一、循环队列1、题目简述2、方法讲解2.1、了解tail的指向2.2、了解空间是如何利用的2.3、如何判断队列是否为空(假溢出问题)?2.4、实现代码 二、用栈实现队列1、题目简述2、方法讲解2.1、讲解2.2、实现代码 三、用队列实现栈1、题目…...

【Hot100】LeetCode—31. 下一个排列

目录 题目1- 思路2- 实现⭐31. 下一个排列——题解思路 3- ACM 实现 题目 原题连接:31. 下一个排列 1- 思路 技巧题,分为以下几个步骤 ① 寻找拐点: i 1 :出现 nums[i1] > nums[i] ,则 i 1 就是拐点 从右向左遍…...

找到学习的引擎,更让你进入心流状态的高效学习

一、心流状态的启动秘籍 1. 简单开始:找到学习的入口 从简单的任务开始,比如整理学习空间或列出学习计划,让大脑逐渐适应学习的节奏。 2. 环境塑造:打造专注的学习空间 清理桌面,减少干扰,比如将手机置…...

QItemDelegate QItemDelegate QItemDelegate

qtreeview点击某一行有颜色显示 c 在Qt中&#xff0c;要实现QTreeView点击某行有颜色显示&#xff0c;可以通过设置QTreeView的itemDelegate来自定义显示样式。以下是一个简单的例子&#xff0c;演示如何为QTreeView的项设置点击时的背景颜色。 #include <QApplication>…...

MySQL数据库 外键默认约束和action 基础知识【2】推荐

数据库就是储存和管理数据的仓库&#xff0c;对数据进行增删改查操作&#xff0c;其本质是一个软件。MySQL就是一种开源的关系型数库&#xff0c;也是最受欢迎的数据库之一&#xff0c;今天对MySQL数据的基础知识做了整理&#xff0c;方便自己查看&#xff0c;也欢迎正在学习My…...

JS正则表达式学习与实践

JS正则表达式学习笔记 1 学习笔记1.1 字符类1.2 量词和分支1.3 标志1.4 锚点1.5 断言 2 常用正则2.1 检查微信浏览器2.2 检查移动端浏览器2.3 检查中文字符2.4 手机号严格2.5 手机号比较宽松2.6 手机号宽松2.7 邮箱验证2.8 金额格式2.9 身份证号2.10 至少8为有数字、大小写字符…...

Java数据结构(五)——栈和队列

文章目录 栈和队列栈基本概念栈的模拟实现集合框架中的栈栈的创建栈的方法栈的遍历 栈的应用及相关练习括号匹配逆波兰表达式求值出栈入栈次序匹配最小栈 几个含"栈"概念的区分 队列基本概念队列的模拟实现循环队列双端队列集合框架中的队列队列的创建队列的方法队列…...

工具使用:nrm使用以及n模块

nrm nrm 是一个npm&#xff08;Node Package Manager&#xff09;的源管理器&#xff0c;它允许用户轻松地在不同的npm源之间进行切换。在Node.js的生态系统中&#xff0c;nrm 提供了一种方便的方式来管理registry源&#xff0c;这对于那些需要从不同的npm源下载或发布包的开发…...

匿名管道+进程池+命名管道

mkfifo name_pipe 创建管道文件。 命名管道&#xff1a; 路径文件名具有唯一性。 匿名管道&#xff1a; 进程池代码&#xff1a; #include<iostream> #include<unistd.h> #include<cstdlib> #include<cassert> #include<vector> #include&…...

【深度学习】【语音TTS】OpenVoice: Versatile Instant Voice Cloning,论文

https://github.com/myshell-ai/OpenVoice https://arxiv.org/abs/2312.01479 文章目录 摘要1 引言2 方法2.1 直观思路2.2 模型结构2.3 训练细节3 结果4 结论摘要 我们介绍了OpenVoice,一种多功能的即时语音克隆方法,只需参考说话者的短音频片段即可复制其声音,并生成多语…...

一六零、云服务器开发机配置zsh

切换shell 在Linux中默认使用/bin/bash&#xff0c;在用户创建时&#xff0c;会自动给用户创建用户默认的shell。默认的shell就是/bin/bash。要修改shell将其设置为/bin/ksh&#xff0c;有两种方法方法 # 方法一: chsh -s /bin/ksh chsh -s /bin/zsh # 方法二: usermod -s /b…...

[ZJCTF 2019]NiZhuanSiWei1

打开题目 php代码审计 .从代码中可以看出要求&#xff0c;以get方式传递text,file,password三个参数。 3.第一层验证if(isset($text)&&(file_get_contents($text,r)"welcome to the zjctf")) 传入text&#xff0c;而且file_get_contents($text,r)之后内容…...

【网络安全】副业兼职日入12k,网安人不接私活就太可惜了!

暑假来了&#xff0c;很多同学后台私信我求做兼职的路子&#xff0c;这里&#xff0c;我整理了一份详细攻略&#xff0c;请大家务必查收&#xff0c;这可能会帮你把几个学期的生活费都赚够&#xff01; Up刚工作就开始做挖漏洞兼职&#xff0c;最高一次赚了12k&#xff0c;后面…...

[STM32]HAL库实现自己的BootLoader-BootLoader与OTA-STM32CUBEMX

目录 一、前言 二、BootLoader 三、BootLoader的实现 四、APP程序 五、效果展示 六、拓展 一、前言 听到BootLoader大家一定很熟悉&#xff0c;在很多常见的系统中都会存在BootLoader。本文将介绍BootLoader的含义和简易实现&#xff0c;建议大家学习前掌握些原理基础。 …...

鸿萌数据备份服务:中小型企业如何策划及实施云备份方案

天津鸿萌科贸发展有限公司从事数据安全服务二十余年&#xff0c;致力于为各领域客户提供专业的数据安全、数据备份、数据恢复、数据清除等解决方案与服务。 对于中小型企业来说&#xff0c;保护运营数据&#xff08;客户记录、财务文档和项目文件&#xff09;的重要性不言而喻…...

x264 编码过程中延迟逻辑分析

编码延迟相关参数 相关参数:在 common.h文件中 frames 结构体中声明关于编码延迟的变量int i_delay; /* Number of frames buffered for B reordering */ int i_bframe_delay; int64_t i_bframe_delay_time;编码延迟计算 编码延迟计算:在x264_encoder_open函数和x264_…...

前端框架 element-plus 发布 2.7.8

更新日志 功能 组件 [级联选择器 (cascader)] 添加持久化属性以提升性能 (#17526 by 0song)[日期选择器 (date-picker)] 类型添加月份参数 (#17342 by Panzer-Jack)[级联选择器 (cascader)] 添加标签效果属性 (#17443 by ntnyq)[加载 (loading)] 补充加载属性 (#17174 by zhixi…...

2024.8.1(前端服务器的配置以及tomcat环境的配置)

回顾 [roottomcat ~]# cd eleme_web/public/img/ [roottomcat img]# ls 1.jpg [roottomcat public]# cd [roottomcat ~]# cd eleme_web/ [roottomcat eleme_web]# cd src [roottomcat src]# vim views/HomeView.vue [roottomcat src]# nohup npm run serve ctrlc后网页不出…...

使用 宝塔面板 部署 语料库php网站

【语料库网站】宝塔面板 在线部署全过程 代码仓库&#xff1a;https://github.com/talmudmaster/RedCorpus 网站介绍 语料库提供双语文本检索和分享功能。供英语、翻译相关专业的爱好者&#xff0c;学生和老师学习使用。 该网站是对BiCorpus开源项目的二次开发。 技术栈&am…...

springboot农产品报价系统-计算机毕业设计源码37300

摘 要 本研究基于鸿蒙系统&#xff0c;设计开发了一款农产品报价系统小程序&#xff0c;旨在帮助商家与买家更便捷、高效地进行交易。该系统利用鸿蒙系统的优势&#xff0c;实现了跨平台应用程序的开发&#xff0c;同时利用定位技术和数据采集技术&#xff0c;为用户提供了个性…...

学做网站会员/拼多多网店代运营要多少费用

1、控件的生命周期——控件消隐之后&#xff0c;会不会依然可点&#xff0c;导致出现进一步的响应&#xff1f;这个之前没想过&#xff0c;之后需要加入到测试点中 2、在登录界面同时出现弹窗&#xff1a; 如&#xff1a;特殊情况下&#xff0c;同时出现弹窗&#xff0c;又刚好…...

十大网页设计网站/襄阳seo推广

递归法总体来说&#xff0c;递归法是从最后一个Node开始&#xff0c;在弹栈的过程中将指针顺序置换的。递归法实现图为了方便理解&#xff0c;我们以 1->2->3->4这个链表来做演示。输出的效果是4->3->2->1首先定义Node&#xff1a;packagecn.liuhaihua;publi…...

做网站还有价值吗/seo排名快速上升

有一个需求需要将前端传过来的10张照片&#xff0c;然后后端进行处理以后压缩成一个压缩包通过网络流传输出去。之前没有接触过用Java压缩文件的&#xff0c;所以就直接上网找了一个例子改了一下用了&#xff0c;改完以后也能使用&#xff0c;但是随着前端所传图片的大小越来越…...

北京大兴最专业的网站建设公司/站内关键词排名软件

1、 选择有效的关键字&#xff1a; 关键字是描述你的产品及服务的词语&#xff0c;选择适当的关键字是建立一个高排名网站的第一步。选择关 键字的一个重要的技巧是选取那些常为人们在搜索时所用到的关键字。 2、 理解关键字&#xff1a; 在你收集所需的关键字之前&#xff…...

驻马店百度seo/seo论坛

前言 现在大多数开发者都有自己的GitHub账号&#xff0c;很多公司也会以是否有GitHub作为一项筛选简历以及人才的选项了&#xff0c;可见拥有一个GitHub账号的重要性&#xff0c;本文就从最基本的GitHub账号的注册到基本的使用进行学习记录&#xff0c;一方面方便自己&#xff…...

seo是付费的吗/南宁百度seo排名公司

2.5 转义字符 用于表示一些不能显示出来的ASCII字符 #include <iostream> using namespace std;int main() {//转义字符//换行符\ncout << "hello world\n" ;//反斜杠 cout << "\\" << endl;//要打两个\\才能输出一个\//水平制表…...