2023年7月21日发(作者:)
定时器存在的弊端,以及解决的⽅法javascript是⼀⼤特点是单线程,也就是说同⼀时间只能做⼀件事,单线程也就意味着,所有任务需要排队,前⼀个任务执⾏完,才会执⾏后⼀个任务,如果前⾯⼀个任务耗时很长,后⼀个任务就不得不等。如果排队是因为CPU忙不过来也就算了,但是很多时候CPU是闲着的,因为IO设备(输⼊输出设备)很慢(⽐如ajax从操作从⽹络读取数据),不得不等着结果出来再往下进⾏。javascript语⾔的设计者意识到,这时候主线程完全可以不管IO设备,挂起处于等待中的任务,先运⾏排在后⾯的任务,等到IO设备返回了结果,再回过头,把挂起的任务继续执⾏下去。于是,所有的任务可以分成两种,⼀种是同步任务,另⼀种是异步任务,同步任务指的是在主线程上排队执⾏的任务,只有前⼀个任务执⾏完毕,才会执⾏下⼀个任务,异步指的是不进⼊"主线程"⽽是进⼊"任务队列的"的任务,只有"任务队列"通知主线程,某个异步任务可以执⾏了,该任务才会进⼊主线程执⾏。具体来说,异步执⾏的运⾏机制如下:1.所有同步任务都在主线程上执⾏,形成⼀个执⾏栈,2.主线程之外还存在⼀个"任务队列",只要异步任务有了结果,就会在"任务队列"中放置⼀个事件3.⼀旦执⾏栈中所有同步任务执⾏完毕,系统就会读取"任务队列",看看⾥⾯有哪些事件,哪些对应的异步任务,于是结束等待状态,进⼊执⾏栈,开始执⾏。4.主线程不断重复上⾯的第三步骤主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运⾏机制⼜称为Event Loop(事件循环);除了放置异步任务的事件,"任务队列"还可以放置定时事件,setTimeout(fn,0)的含义是,指定任务在主线程最早可得的空闲时间执⾏,也就是说,尽可能早的执⾏,他在"任务队列"尾部添加⼀个事件,因此要等到同步任务和"任务队列"现在的事件执⾏完以后,才会得到执⾏需要注意的是,定时器只是在指定的时间将事件插⼊到"任务队列",必须等到执⾏栈中当前的代码(同步任务以及"任务队列"当前任务)执⾏完以后,主线程才会执⾏他指定的回调函数,如果当前代码执⾏耗时很长,有可能要等很久,所以并没有办法保证,回调函数⼀定在定时器规定的时间执⾏,⽐如下⾯的代码:上⾯的代码,定时器在1000毫秒时加⼊"任务队列",但是此时同步代码for循环还没有执⾏完,可能需要很长的时间,所以当for执⾏完以后会⽴即输出0和1,0和1的输出也没有体现出间隔1000毫秒的时间,⽽此时setTime回调函数执⾏的时候时间远远⼤于1000毫秒再⽐如: < script >startFn2();function startFn2() { var p2 = new AlarmClockByInterval(callBackByTest, 2000);}function callBackByTest() { var i = 0; for (; i < 9000000000; i++) { } return true;}function AlarmClockByInterval(_args1, _args2) { var timeFn, self = this; callBackFn = _args1; ms = _args2; i = 0; erval = function() { if (ms) { if (!timeFn) { timeFn = setInterval(function() { ("定时任务开始执⾏:" + new Date().getTime()); callBackFn(); ("定时任务结束执⾏:" + new Date().getTime()); }, ms) } } else { closeInterval(); } } nterval = function() { if (timeFn) { closeInterval(timeFn); } } erval();}< /script>
上⾯的代码,定时任务⼀旦执⾏完毕,会⽴即执⾏下⼀次任务,并没有理想中的间隔,直接⽤setInterval并不能获得我们理想中的效果对于上⾯的问题,我们如何解决呢?使⽤setTimeOut,和递归,利⽤函数⾃动调⽤⾃⾝,延时执⾏就可以很好的解决这个问题
发布者:admin,转转请注明出处:http://www.yc00.com/web/1689924140a294869.html
评论列表(0条)