首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

可能是最简单的 JS 并发控制方案

近期刷到了一些关于前端并发控制的文章,感觉有些人对并发控制有些误解,想起自己很多年前写一个扫描脚本的时候,由于数据量过大,为了让脚本能够运行的更快些写了一个并发控制的库: node-job-runner,现在回头看来着实有些简陋。想想不如乘机写(水)一篇。

想要直接看方案抄作业的可直接跳到下方 伪线程方案 查看。

并发控制

咱们先从什么是并发控制唠起。并发控制其实在后端算是一个比较困难的问题,因为后端的并发控制大部分情况下指的是高并发场景下多个用户或程序同时访问或修改数据时对操作进行管理。这就涉及到资源锁定、操作排序、隔离等等。

不过在前端所聊的并发控制就很简单了,一般指的是前端发起请求或其他一些异步操作时为了控制并发的请求或操作数量而做的控制。

使用场景

常见的使用并发控制的场景如下:

浏览器请求并发量控制:每个浏览器都存在并发请求上限( 之前),所以如果一次发送的请求过多,将会阻塞后续的其他请求。比如有一个表格需要一次性加载几万条数据,需要每次 100 条从 拉取,这就需要创建几百个请求任务,如果一次性将这些请求全部打满,后续万一有了更高优先级的请求则一定会需要排队等待前面的几百个请求完成才可以。

脚本扫描并发量控制:如果需要使用 去做一些扫描任务,通常需要并发大量请求来提高执行速度,然而如果并发过高则会出现请求直接报错或者是描述符超限的情况。

所以如果异步任务并发较高且容易导致问题的场景就需要做好并发控制。

实现方案

计数器方案

要实现并发控制,最简单常见的方案便是通过计数器来控制并发数量,我们以 实现来演示:

事例中通过 来控制并发数量,第一个 当 小于 时,就会继续执行 方法,从而在一开始将并发数量提升到 个,然后后续每次 执行完成后都会继续调用下一个 来填补空余,从而将并发数量一直维持在 个。每次请求的执行结果都通过索引将其保存到 中的对应位置,当最后一个请求完成后 就会触发 ,从而返回结果。

但其实,上述的代码存在一些漏洞:

如果 的长度 小于等于 ,那么就会导致第一个 语句时 从而提前 ,解决倒也简单,直接增加一个完成的计数器,然后把完成的条件判断放到每个任务完成时判定即可。

如果 的长度为 0,将永远无法触发 ,这个问题也很好解决,提前判断一下 的长度即可。

所以最终改造后的代码如下:

伪线程方案

再来看看我平时用到的另一种更简单的方案,我不太清楚怎么命名,姑且称之为伪线程方案。主要思路就是模拟线程的设计,开几个线程,每个线程去任务栈中取任务,当所有线程都完成时则代表所有任务完成即可返回结果。

乍看之下可能会觉得代码量差不多,实则不然,这种方案的可读性和代码量其实都优于上一个方案。首先通过 快速创建出一个长度为 的线程池,然后在每个线程中会去 中一个个拿取带处理的数据,通过 直到将数据全部处理完成。也不用担心 长度小于 等边界情况。

如果不需要返回结果,那么这种方案就会显得更为简洁。

可以看出,核心代码不过数行,而且可读性也很高。个人觉得时目前最简单的并发控制方案。

总结

其实可以看出,前端的并发控制其实非常简单,做好限制并想办法依次处理未处理的数据即可。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O97cYFmAWlqWBMzj1YkB12XA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券