一、背景由于电脑CPU和内存的限制,可以同时启动的任务数是有限的。例如,一台计算机可以执行5个异步任务,但目前有100个异步任务。任务是要执行的,那么这100个任务如何做到无间隔快速执行呢?2.问题解答第一次遇到这个问题的时候,我也是一头雾水,怎么处理呢???刚好最近学习了一些vue源码知识,能不能用他的思路来解决这个问题呢?经过一步一步的分析,确定答案是肯定的。下面从解题思路、知识点和代码实现说说实现过程。2.1解题思路以上是整个流程图,其过程可以简化为以下步骤:将所有任务分成两组,任务组1指的是计算机可以并行执行的异步任务,任务组2指rest异步任务;将taskgroup1变为framelistening状态,即我们可以知道它什么时候发生变化;触发任务组1中的任务(任务不触发不执行);任务执行完成后,任务组2中的任务之一在帧监听状态下被填充到任务组1中;任务按照固定的数量不断执行,直到所有任务执行完毕。2.2知识点在Vue源码中,Vue2.x使用了Object.defineProperty()来实现frame监听数据;Vue3.0使用Proxy实现框架监听数据。本着紧跟潮流的态度和Proxy确实优秀的态度,在实现过程中也应用了Proxy。Proxy作为一个新的知识点,首先了解一下它的定义和用法。2.2.1定义Proxy中文意思是“代理”,就是在目标对象之间设置一层“拦截”,从而可以修改某些操作的默认行为。Proxy一共支持13种拦截操作:get、set、has、deleteProperty、ownKeys、getOwnPropertyDescriptor、defineProperty、preventExtensions、getPrototypeOf、isExtensible、setPrototypeOf、apply、construct。2.2.2简单使用functiontestProxy(obj){returnnewProxy(obj,{get:(target,key)=>{console.log(`我被get拦截器拦截了,拦截的属性是${key}`);},set:(target,key,value)=>{console.log(`我被set拦截器拦截了,拦截的属性是${key},新的value是${value}`);target[key]=value;}});}consttestObj={a:10};constproxy=testProxy(testObj);proxy.a=100;2.2.3详细用法参考《ECMAScript6入门》”。2.3代码实现2.3.1定义两个任务队列首先定义两个任务队列,task1是一批要执行的任务,task2是后面加入的任务。consttask1=[1,2,3];consttask2=[4,5,6,7,8];2.3.2数据变为frame-listenable的功能使用Proxy将数据变为frame-listenable状态/***监听模块,监听对应数组的变化,保证其始终有一定长度的内容运行**@param{Array}initArr定长任务数组*@param{Function}callback对应的回调函数*/functionwatcher(initArr,callback){constproxy=newProxy(initArr,{set(target,key,value,receiver){target[key]=value;callback(value,key,receiver);}});返回代理;}2.3。3异步任务逻辑/***异步任务的运行逻辑**@param{number}taskIndex异步任务的序号*@param{number}index定长任务中当前任务的序号*@param{Proxy}proxy代理实例*/functionasyncTask(taskIndex,index,proxy){console.log(`${index}处的任务${taskIndex}开始执行`);returnnewPromise(resolve=>{setTimeout(()=>{console.log(`${index}索引处的任务${taskIndex}已执行`);//当任务队列中有任务时2,进入队列替换任务1中执行的任务if(task2.length>0){proxy[index]=task2.shift();}},1000+2000*Math.random());});}2.3.4main函数constproxy=watcher(task1,as异步任务);task1.forEach((taskIndex,index)=>asyncTask(taskIndex,index,proxy));}2.3.5执行结果从结果可以看出,当一个task完成后,会立即有一个新的task进入0task1atindex开始执行1Task2atindex开始执行2Task3atindex开始执行0Task1atindex完成0Task4atindex开始执行2Task3atindex结束执行2AtindexTask5atindex1开始执行任务2atindex1完成执行任务6atindex0开始执行任务4atindex0完成执行任务7atindex2开始执行taskatindex25完成执行taskatindex28开始执行task6atindex1完成执行0Task7atindex2Completeexecution2Task8atindexComplete3.讨论如何处理这类问题。如果您有新的想法和方法,欢迎留言。我们共同探讨,共同进步。1.如果你觉得这篇文章还不错,请分享点赞,让更多人看到。2.关注公众号致远领取学习资料(前端“多臂”资料),定期投稿优推原创深度文章
