控制并发执行的解决方法(队列控制类)

前言

之前我有一篇文章(组件阅后即焚?挂载即卸载!看完你就理解了 - 掘金 (juejin.cn))提到了,工作生涯接到过一个需求是批量导出学生二维码,其中有个问题在于使用html2canvas时,会同时产生大量canvas标签占用内存导致页面卡顿甚至崩溃的问题。

思路

其实很简单,最大的原因是同时存在过多的canvas标签,占用了过多的内存,而同样作为一个热门的第三方库,html2canvas其实会主动删除自己复制的dom元素,但在并发量过的情况下,释放的速度比不上生成的速度,所以会出现问题。

那么解决方案也就是控制它的生成速度,以保障释放速度在承受范围之内。

但这里很有意思的一点是,不同电脑的承受范围是不一样的,不同的canvas占用的内存也是不一样的,所以如何控制这个量是要自己掌握的。

像一些不好掌握的情况,我的建议是直接服务端整一个服务专门用来批量执行这样的任务。

当然了,这里我们直接写个最简单易懂的方案来做就好了,控制并发量。

编程!启动!

众所周知,JS是世界上最好的语言(bushi)

hhhhh,玩个梗。

那么,为了通用,所以我们还是会以一些比较好用的方式也来设计这个东西,就决定用类class来做这个方案的载体。也就是并发队列控制类

这里我就直接放上代码,供大家参考了

js 复制代码
class ConcurrencyControllerQueue<T> {
  activeCount: number
  values: T[]

  private tasks: Array<() => Promise<T>>
  private readonly maxConcurrency: number

  constructor(maxConcurrency: number) {
    this.tasks = []
    this.values = []
    this.maxConcurrency = maxConcurrency
    this.activeCount = 0
  }

  // 将一个任务添加到队列并立即执行
  public pushTask(fn: () => Promise<T>): void {
    if (this.activeCount >= this.maxConcurrency) {
      this.tasks.push(fn)
    } else {
      this.runTask(fn)
    }
  }
  
  public clearTask(): void {
    this.tasks = []
  }

  public clearValues(): void {
    this.values = []
  }
  
  // 从队列中取出一个任务并执行
  private runTask(fn: () => Promise<T>): void {
    this.activeCount++
    fn().then((value) => {
      this.values.push(value)
      this.activeCount--
      if (this.tasks.length > 0) {
        this.runTask(this.tasks.shift()!)
      }
    })
  }
}

这个类的组成成分其实还蛮清晰的: activeCount: 当前正在活动的任务数 values: 这里我是因为学生的二维码需要以Blob数据作为任务结果,所以需要这么个东西

private tasks: 就是当前正在等待的任务队列 private readonly maxConcurrency: 最大的同时执行任务数量,这里因为觉得一个实例就单一处理一个并发量,就不让它能更改了,所以是只读

方法成员就不跟大家介绍了,方法名简单易懂

这里其实还能做更多扩展,比如设置暂停和重启、修改并发量、只是将任务添加进队列但不立即启动等等......

因为像这些扩展都并不难,且现有功能已满足了我的需求,所以就先这样,等以后有需要再修改便可。

相关推荐
不在逃避q4 分钟前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁18 分钟前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One98524 分钟前
高进度算法模板速记(待完善)
java·前端·算法
陈随易29 分钟前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师2 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174462 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈2 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen3 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒3 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端
梅孔立4 小时前
两种免费的翻译API调用方式详解 - Edge官方API与个人缓存服务
前端·缓存·edge