版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2025年高频js的一道面试题及答案实现一个支持动态并发控制的异步任务调度器,要求满足以下功能:1.初始化时设置最大并发数`concurrency`(默认3)2.支持动态添加异步任务(任务为返回Promise的函数)3.保证同一时刻运行的任务数不超过`concurrency`4.任务按添加顺序执行(非严格顺序,即不阻塞后续任务启动,但最终结果按完成顺序输出时需保留原始队列顺序标识)5.支持捕获单个任务的错误(不中断整体调度)6.提供`pause()`和`resume()`方法控制任务执行(暂停时不启动新任务,恢复后继续)7.提供`cancel()`方法终止所有未执行任务(已执行任务继续完成)8.提供`on('finish',callback)`事件监听所有任务完成请完成该调度器的代码实现,并说明核心设计思路。核心设计思路调度器的核心在于对任务队列的管理和并发数的动态控制。关键模块包括:1.任务队列:存储待执行的任务及其上下文(如唯一标识、入队时间等),需支持高效的插入和取出操作。考虑到任务可能动态添加,采用链表结构比数组更适合频繁的插入操作。2.并发控制器:维护当前正在执行的任务数量`activeCount`,每次启动新任务前检查`activeCount<concurrency`,若满足则从队列取出任务执行,否则等待。3.状态管理:维护`isPaused`(暂停状态)、`isCancelled`(取消状态)等标志位,控制任务是否允许启动。4.错误处理:单个任务通过`catch`捕获错误,将错误信息与任务标识关联存储,不影响其他任务执行。5.事件系统:使用观察者模式实现`on`方法,当所有任务完成(队列空且`activeCount=0`)时触发`finish`事件。6.动态控制:`pause()`设置`isPaused=true`,后续任务启动时检查该状态;`resume()`则重置状态并尝试启动新任务;`cancel()`标记`isCancelled=true`,清空队列中未执行任务。代码实现```javascriptclassAsyncTaskScheduler{constructor(concurrency=3){this.concurrency=Math.max(1,concurrency);//最小并发数1this.activeCount=0;//当前执行中的任务数this.taskQueue=newLinkedList();//任务队列(链表实现)this.isPaused=false;//暂停状态this.isCancelled=false;//取消状态this.results=newMap();//存储任务结果(key:taskId,value:{result,error})this.finishCallbacks=newSet();//finish事件回调集合this.taskId=0;//任务唯一标识计数器}//添加任务(支持单个或多个任务)add(tasks){if(this.isCancelled){thrownewError('Schedulerhasbeencancelled');}consttaskList=Array.isArray(tasks)?tasks:[tasks];taskList.forEach(task=>{if(typeoftask!=='function'){thrownewTypeError('TaskmustbeafunctionreturningaPromise');}consttaskId=this.taskId++;this.taskQueue.append({taskId,executor:task,createdAt:Date.now()});});this._tryRunTasks();//添加后尝试启动任务}//尝试运行任务(核心逻辑)_tryRunTasks(){if(this.isPaused||this.isCancelled||this.activeCount>=this.concurrency){return;}//循环启动任务直到达到并发限制或队列为空while(this.activeCount<this.concurrency&&!this.taskQueue.isEmpty()){consttaskNode=this.taskQueue.shift();//取出队首任务if(!taskNode)break;const{taskId,executor}=taskNode.value;this.activeCount++;//执行任务(用Promise.resolve包装确保是Promise)Promise.resolve().then(()=>executor()).then(result=>{this.results.set(taskId,{result,error:null});}).catch(error=>{this.results.set(taskId,{result:null,error});}).finally(()=>{this.activeCount--;//任务完成后检查是否全部完成if(this.taskQueue.isEmpty()&&this.activeCount===0){this._emitFinish();}//继续尝试运行剩余任务this._tryRunTasks();});}}//暂停调度(不影响已执行任务)pause(){this.isPaused=true;}//恢复调度resume(){if(this.isCancelled){thrownewError('Cannotresumeacancelledscheduler');}this.isPaused=false;this._tryRunTasks();//恢复后尝试启动任务}//取消调度(清空未执行任务)cancel(){this.isCancelled=true;this.taskQueue.clear();//清空队列this.results.clear();//清空结果(可选,根据需求保留已完成结果)}//监听完成事件on(event,callback){if(event==='finish'){this.finishCallbacks.add(callback);}}//触发完成事件_emitFinish(){constresults=Array.from(this.results.entries()).map(([taskId,{result,error}])=>({taskId,result,error,success:error===null}));this.finishCallbacks.forEach(callback=>callback(results));}}//辅助:链表节点classListNode{constructor(value){this.value=value;this.next=null;}}//辅助:链表实现(支持高效的头部删除和尾部添加)classLinkedList{constructor(){this.head=null;this.tail=null;this.size=0;}//尾部添加节点append(value){constnewNode=newListNode(value);if(!this.head){this.head=newNode;this.tail=newNode;}else{this.tail.next=newNode;this.tail=newNode;}this.size++;}//头部移除节点并返回shift(){if(!this.head)returnnull;constremoved=this.head;this.head=this.head.next;if(!this.head){this.tail=null;}this.size--;returnremoved;}//是否为空isEmpty(){returnthis.size===0;}//清空链表clear(){this.head=null;this.tail=null;this.size=0;}}```关键点解析1.任务队列的选择:使用链表而非数组,因为需要频繁在尾部添加任务(`append`)和头部取出任务(`shift`),链表的时间复杂度为O(1),而数组的`shift`操作是O(n),链表更适合高频率操作场景。2.并发控制逻辑:`_tryRunTasks`方法通过`while`循环持续检查当前活跃任务数(`activeCount`)和队列状态,确保在未暂停、未取消且未达并发上限时尽可能启动新任务。3.错误隔离机制:每个任务通过`catch`捕获错误,将结果(包括错误)存储在`results`中,避免单个任务失败导致整个调度器崩溃。4.暂停/恢复实现:`isPaused`标志位在`_tryRunTasks`的入口处进行检查,暂停时直接返回,恢复时重置标志位并重新触发任务启动逻辑。5.取消操作处理:`cancel()`方法设置`isCancelled`标志位并清空队列,后续添加任务会直接抛出错误,已执行的任务继续完成(符合“终止所有未执行任务”的需求)。6.完成事件触发:在`finally`回调中检查队列是否为空且无活跃任务,满足条件时触发`finish`事件,传递包含所有任务结果(含错误)的数组。扩展讨论任务优先级支持:可将链表改为优先队列(如堆结构),任务入队时根据优先级排序,`_tryRunTasks`从堆顶取出高优先级任务执行。需注意调整`append`和`shift`的实现逻辑。超时控制:为每个任务添加超时设置(如通过`Promise.race`结合`setTimeout`),超时后标记任务为失败,避免长时间阻塞队列。动态调整并发数:添加`setConcurrency(newConcurrency)`方法,调整`concurrency`值后调用`_tryRunTasks`,可能触发更多任务启动(若新并发数更大)或保持现状(若更小)。任务进度跟踪:在`resul
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年大学第三学年(汉语言文学)比较文学基础试题及答案
- 高职第三学年(健康管理)健康评估实务2026年综合测试题及答案
- 2025年高职作物生产与经营管理(作物营养调控)试题及答案
- 高职第一学年(建筑工程技术)砌体结构施工2026年综合测试题及答案
- 2025年大学大一(法学)法理学阶段测试题及答案
- 2026年数据库(数据库技术)综合测试题及答案
- 2025年大学第一学年(世界文化地理)文化差异阶段测试试题及答案
- 2025年大学一年级(化学工程与工艺)化工热力学试题及答案
- 2025年大学(广告学)广告学概论试题及答案
- 2025年高职(音乐制作)音乐编曲试题及答案
- 2024-2025学年广东省广州市越秀区八年级上学期期末考试物理试卷(含答案)
- AI与智慧图书馆双向赋能
- 《中药的现代化》课件
- 生物专业英语翻译-蒋悟生
- 高速铁路客运规章(第2版)课件 项目五 高速铁路旅客运输服务管理
- 基础医学概论期末考试试卷
- 自愿离婚协议书标准样本(八篇)
- 食品营养学(暨南大学)智慧树知到期末考试答案章节答案2024年暨南大学
- 重庆市两江新区2022-2023学年五年级下学期期末数学试题
- 闺蜜测试卷试题
- 基于DSP的抢答器的设计与开发
评论
0/150
提交评论