iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >JavaScript中如何实现并发控制
  • 330
分享到

JavaScript中如何实现并发控制

2024-04-02 19:04:59 330人浏览 泡泡鱼
摘要

这篇文章将为大家详细讲解有关javascript中如何实现并发控制,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、前言在开发过程中,有时会遇到需要控制任务

这篇文章将为大家详细讲解有关javascript中如何实现并发控制,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

一、前言

开发过程中,有时会遇到需要控制任务并发执行数量的需求。

例如一个爬虫程序,可以通过限制其并发任务数量来降低请求频率,从而避免由于请求过于频繁被封禁问题的发生。

接下来,本文介绍如何实现一个并发控制器。

二、示例

const task = timeout => new Promise((resolve) => setTimeout(() => {       resolve(timeout);     }, timeout))       const taskList = [1000, 3000, 200, 1300, 800, 2000];      async function startNoConcurrentControl() {       console.time(NO_CONCURRENT_CONTROL_LOG);       await Promise.all(taskList.map(item => task(item)));      console.timeEnd(NO_CONCURRENT_CONTROL_LOG);     }     startNoConcurrentControl();

上述示例代码利用 Promise.all 方法模拟6个任务并发执行的场景,执行完所有任务的总耗时为 3000 毫秒。

下面会采用该示例来验证实现方法的正确性。

三、实现

由于任务并发执行的数量是有限的,那么就需要一种数据结构来管理不断产生的任务。

队列的**「先进先出」特性可以保证任务并发执行的顺序,在 JavaScript 中可以通过「数组来模拟队列」**:

class Queue {        constructor() {          this._queue = [];        }          push(value) {          return this._queue.push(value);        }          shift() {          return this._queue.shift();        }        isEmpty() {          return this._queue.length === 0;       }      }

对于每一个任务,需要管理其执行函数和参数:

class DelayedTask {        constructor(resolve, fn, args) {          this.resolve = resolve;          this.fn = fn;          this.args = args;        }      }

接下来实现核心的 TaskPool 类,该类主要用来控制任务的执行:

class TaskPool {        constructor(size) {          this.size = size;          this.queue = new Queue();       }          addTask(fn, args) {          return new Promise((resolve) => {            this.queue.push(new DelayedTask(resolve, fn, args));          if (this.size) {              this.size--;              const { resolve: taskResole, fn, args } = this.queue.shift();              taskResole(this.runTask(fn, args));            }          })        }        pullTask() {          if (this.queue.isEmpty()) {            return;          }          if (this.size === 0) {            return;          }          this.size++;          const { resolve, fn, args } = this.queue.shift();          resolve(this.runTask(fn, args));        }        runTask(fn, args) {          const result = Promise.resolve(fn(...args));           result.then(() => {           this.size--;            this.pullTask();          }).catch(() => {            this.size--;            this.pullTask();         })           return result;       }      }

TaskPool 包含三个关键方法:

  •  addTask: 将新的任务放入队列当中,并触发任务池状态检测,如果当前任务池非满载状态,则从队列中取出任务放入任务池中执行。

  •  runTask: 执行当前任务,任务执行完成之后,更新任务池状态,此时触发主动拉取新任务的机制。

  •  pullTask: 如果当前队列不为空,且任务池不满载,则主动取出队列中的任务执行。

JavaScript中如何实现并发控制

接下来,将前面示例的并发数控制为2个:

const cc = new ConcurrentControl(2);        async function startConcurrentControl() {        console.time(CONCURRENT_CONTROL_LOG);        await Promise.all(taskList.map(item => cc.addTask(task, [item])))        console.timeEnd(CONCURRENT_CONTROL_LOG);      }        startConcurrentControl();

执行流程如下:

JavaScript中如何实现并发控制

最终执行任务的总耗时为 5000 毫秒。

四、高阶函数优化参数传递

await Promise.all(taskList.map(item => cc.addTask(task, [item])))

手动传递每个任务的参数的方式显得非常繁琐,这里可以通过**「高阶函数实现参数的自动透传」**:

addTask(fn) {       return (...args) => {          return new Promise((resolve) => {            this.queue.push(new DelayedTask(resolve, fn, args));            if (this.size) {              this.size--;              const { resolve: taskResole, fn: taskFn, args: taskArgs } = this.queue.shift();              taskResole(this.runTask(taskFn, taskArgs));            }          })        }      }

改造之后的代码显得简洁了很多:

await Promise.all(taskList.map(cc.addTask(task)))

五、优化出队操作

数组一般都是基于一块**「连续内存」**来存储,当调用数组的 shift 方法时,首先是删除头部元素(时间复杂度 O(1)),然后需要将未删除元素左移一位(时间复杂度 O(n)),所以 shift 操作的时间复杂度为 O(n)。

JavaScript中如何实现并发控制

由于 JavaScript 语言的特性,V8 在实现 jsArray 的时候给出了一种空间和时间权衡的解决方案,在不同的场景下,JSArray 会在 FixedArray 和 HashTable 两种模式间切换。

在 hashTable 模式下,shift 操作省去了左移的时间复杂度,其时间复杂度可以降低为 O(1),即使如此,shift 仍然是一个耗时的操作。

在数组元素比较多且需要频繁执行 shift 操作的场景下,可以通过 「reverse + pop」 的方式优化

const Benchmark = require('benchmark');      const suite = new Benchmark.Suite;        suite.add('shift', function() {        let count = 10;        const arr = generateArray(count);        while (count--) {          arr.shift();        }     })     .add('reverse + pop', function() {        let count = 10;        const arr = generateArray(count);        arr.reverse();        while (count--) {          arr.pop();        }      })      .on('cycle', function(event) {        console.log(String(event.target));      })      .on('complete', function() {        console.log('Fastest is ' + this.filter('fastest').map('name'));        console.log('\n')      })      .run({        async: true      })

通过 benchmark.js 跑出的基准测试数据,可以很容易地看出哪种方式的效率更高:

JavaScript中如何实现并发控制

回顾之前 Queue 类的实现,由于只有一个数组来存储任务,直接使用 reverse + pop 的方式,必然会影响任务执行的次序。

这里就需要引入双数组的设计,一个数组负责入队操作,一个数组负责出队操作。

class HighPerfORManceQueue {       constructor() {         this.q1 = []; // 用于 push 数据         this.q2 = []; // 用于 shift 数据       }         push(value) {         return this.q1.push(value);      }       shift() {         let q2 = this.q2;        if (q2.length === 0) {           const q1 = this.q1;           if (q1.length === 0) {             return;           }           this.q1 = q2; // 感谢 @shaonialife 同学指正           q2 = this.q2 = q1.reverse();         }         return q2.pop();       }       isEmpty() {         if (this.q1.length === 0 && this.q2.length === 0) {         return true;        }         return false;       }     }

最后通过基准测试来验证优化的效果:

JavaScript中如何实现并发控制

关于JavaScript中如何实现并发控制就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: JavaScript中如何实现并发控制

本文链接: https://www.lsjlt.com/news/70204.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript 中如何实现并发控制
    目录一、并发控制简介1.1 阶段一1.2 阶段二1.3 阶段三二、并发控制的实现2.1 asyncPool 的使用2.2 asyncPool ES7 实现2.3 asyncPool ...
    99+
    2024-04-02
  • JavaScript中如何实现并发控制
    这篇文章将为大家详细讲解有关JavaScript中如何实现并发控制,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、前言在开发过程中,有时会遇到需要控制任务...
    99+
    2024-04-02
  • JavaScript中怎么实现并发控制
    这篇文章给大家分享的是有关JavaScript中怎么实现并发控制的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 在日常开发过程中,你可能会遇到并发控制...
    99+
    2024-04-02
  • JavaScript中实现并发控制的方法
    这篇文章将为大家详细讲解有关JavaScript中实现并发控制的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、并发控制简介在日常开发过程中,你可能会遇到并发控制的场景,比如控制请求并发数。那么在 ...
    99+
    2023-06-15
  • 如何在PostgreSQL中实现多版本并发控制
    在PostgreSQL中,多版本并发控制是通过使用MVCC(Multi-Version Concurrency Control)机制...
    99+
    2024-04-09
    PostgreSQL
  • MySQL中怎么实现并发控制
    今天就跟大家聊聊有关MySQL中怎么实现并发控制,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。锁锁分为读锁和写锁两种,也称作共享锁和排他锁。因为多个...
    99+
    2024-04-02
  • 如何在 ASP 教程中实现接口并发控制?
    ASP是一种常见的Web应用程序框架,用于开发动态网站和Web应用程序。在开发ASP应用程序时,我们经常需要考虑如何实现接口并发控制,以确保系统的稳定性和可靠性。本文将介绍如何在ASP教程中实现接口并发控制,并提供相应的示例代码。 一、什么...
    99+
    2023-11-07
    教程 接口 并发
  • 如何在ASP.NET应用程序中实现并发控制?
    在ASP.NET应用程序中实现并发控制是一个非常重要的问题。在这个过程中,我们需要考虑多个用户同时访问应用程序的情况,以确保应用程序在高负载下能够正常运行。 一、 什么是并发控制? 并发控制是指在多个用户同时访问应用程序时,通过一些手段来确...
    99+
    2023-07-20
    并发 spring 日志
  • 如何在Java和Django中实现高效的并发控制?
    随着互联网的快速发展,高并发的情况越来越普遍。在Java和Django中实现高效的并发控制是非常重要的。在本文中,我们将介绍一些在Java和Django中实现高效的并发控制的方法,并提供相应的代码演示。 一、Java中的并发控制 在Java...
    99+
    2023-09-10
    django 同步 并发
  • JavaScript如何实现控制视频
    这篇文章将为大家详细讲解有关JavaScript如何实现控制视频,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体代码如下所示:<html lang=&q...
    99+
    2024-04-02
  • JavaScript如何利用Promise控制并发请求个数
    一、场景 假设现在有这么一种场景:现有 30 个异步请求需要发送,但由于某些原因,我们必须将同一时刻并发请求数量控制在 5 个以内,同时还要尽可能快速的拿到响应结果。 如图所示: ...
    99+
    2024-04-02
  • 如何使用Java和Git实现Django的并发控制?
    Django是一个流行的Python web框架,它以简单易用和高效稳定著称。然而,在高并发的情况下,Django可能会遇到一些性能问题。这时,使用Java和Git来实现Django的并发控制是一个不错的选择。本文将介绍如何使用Java和...
    99+
    2023-10-16
    git django 并发
  • golang控制并发数怎么实现
    在Go语言中,可以使用goroutine和channel来实现并发控制。下面是一种常见的实现方式: 创建一个有缓冲的channel...
    99+
    2023-10-21
    golang
  • Java和Django的同步技术:如何实现并发控制?
    Java和Django是两个非常流行的开发框架。Java是一种面向对象的编程语言,广泛应用于企业级应用程序的开发。Django是一个基于Python的Web框架,广泛应用于Web应用程序的开发。虽然这两个框架有着不同的编程语言和应用场景,但...
    99+
    2023-09-10
    django 同步 并发
  • JavaScript如何控制Session的实现原理
    本篇内容主要讲解“JavaScript如何控制Session的实现原理”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript如何控制Session的...
    99+
    2024-04-02
  • 如何在Go语言中实现JavaScript中的并发?
    JavaScript是一种广泛使用的编程语言,它具有良好的并发处理能力。但是,Go语言同样是一种非常强大的编程语言,它也具有非常出色的并发处理能力。在本文中,我们将介绍如何在Go语言中实现JavaScript中的并发。 一、JavaScr...
    99+
    2023-06-23
    并发 javascript 面试
  • 微服务架构如何实现服务间的并发控制?
    随着信息技术的不断发展,微服务架构已成为当今互联网领域中最受欢迎的架构之一。微服务架构采用小型服务组件化的方式来构建应用程序,每个服务组件都独立运行,并通过轻量级的通信机制相互协作。但是,由于微服务架构中服务之间的高度耦合和紧密联系,服务之...
    99+
    2023-05-17
    并发控制 微服务架构 服务间通信
  • 如何配置apache中并发控制参数prefork
    本篇内容介绍了“如何配置apache中并发控制参数prefork”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一个apache有linux下...
    99+
    2023-06-10
  • 如何基于JS实现Ajax并发请求的控制详解
    目录前言 Ajax的串行与并行Ajax的并发请求控制的两大解决方案 基于Promise递归实现 基于Class实现 代码展示 总结 前言 最近看到一个面试题,当然了,就是这篇文章的...
    99+
    2024-04-02
  • ASP并发教程API:如何通过API实现分布式系统的并发控制?
    在分布式系统中,由于数据访问的并发性,很容易出现数据冲突的情况。为了避免这种情况的发生,需要进行并发控制。ASP.NET提供了一些API来帮助我们实现分布式系统的并发控制。 一、ASP.NET并发控制的基本原理 ASP.NET并发控制的基...
    99+
    2023-07-07
    并发 教程 api
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作