作者在管理setTimeout&setInterval这两个API时,一般会在***(全局)作用域中创建一个名为timer的对象,其下面有两个数组成员——sto,siv},用它们分别存放需要管理的setTimeoutID/setIntervalID。如下:vartimer={sto:[],siv:[]};使用setTimeout/setInterval时,这样调用://marksetTimeoutIDtimer.sto.push(setTimeout(function(){console.log("3s")},3000);//MarksetIntervalIDtimer.siv.push(setInterval(function(){console.log("1s")},1000));当页面需要clearTimeout\clearInterval时,这样调用://批量清除setTimeouttimer.sto.forEach(function(sto){clearTimeout(sto)});//批量清除setIntervaltimer.siv.forEach(function(siv){clearInterval(四)});Pause&resume最近一段时间,笔者发现很多业务需要“暂停”和“恢复”setTimeout&setInterval的功能,但是原来的四个API(setTimeout/setIntervale/clearTimeout/clearInterval)已经不够用了。因此,作者对定时器进行了扩展,使其具有“暂停”和“恢复”的功能,如下://PauseallsetTimeout&setIntervaltimer.pause();//ResumeallsetTimeout&setIntervaltimer.resume();扩展后定时器对象下挂载了六个基本API。setTimeoutsetIntervalclearTimeoutclearIntervalpauseresume使用timer.set*&timer.clear*而不是原生的set*&clear*。作者将扩展定时器托管在GitHub仓库上。有兴趣的同学可以移步:https://github.com/leeenx/timerCreateJS灵感在使用CreateJS开发一些项目的过程中,笔者发现通过设置createjs.Ticker.paused=true/false来暂停/恢复动画创建js.Tween。于是作者借用了createjs.Tween来模拟setTimeout&setInterval的功能,如下://setTimeoutcreatejs.setTimeout=function(fn,delay){createjs.Tween.get().wait(delay).call(fn);}//setIntervalcreatejs.setInterval=function(fn,delay){createjs.Tween.get().wait(delay).call(fn).loop=1;}具体代码作者托管于:createjs.timer.其实就是在createjs对象下挂载了四个API:setTimeoutsetIntervalclearTimeoutclearInterval使用的方法和原来的setTimeout&setInterval一样,如下:letsiv=createjs.setInterval(()=>console.log("1s"),1000);createjs.setTimeout(()=>createjs.clearInterval(siv),5000);时间轴驱动的定时器createjs.timer给笔者在CreateJS项目开发中带来了极大的方便,但是必须依赖createjs.Tween模块。所以笔者在思考要不要做一个和第三方框架无关,可以在第三方框架上使用的定时器。为什么createjs.Ticker.paused可以暂停createjs.Tween上的动画?createjs.Tween中的每个动画都有自己的时间线,由createjs.Ticker驱动;当createjs.Ticker被暂停后,createjs.Tween中各个动画的时间线也会失去动力而暂停。createjs.Ticker的作用是提供刷新canvas屏幕的帧率,通常使用requestAnimationFrame或者setInterval来实现。如果定时器内部有一个时间轴,由第三方驱动,那么定时器就可以同步到第三方框架的状态。作者将定时器的结构设计如下:queue——存放setTimeout或setInterval的队列;updateQueue-驱动队列的内部API;update-用于连接到第三方Ticker的外部接口。实现的伪代码如下:/*@queue成员结构如下:{fn:fn,//回调函数类型:"timeoutorinterval",//typeelapsed:0,//时间轴进度延迟:delay//目标持续时间}*/letqueue=newMap();functionupdateQueue(delta){queue.forEach((item,id)=>{item.elapsed+=delta;if(item.elapsed>=item.delay){item.fn();//从队列中删除setTimeout成员,interval成员继续循环item.type==="timeout"?delete(id):(item.elapsed=0);}});}//外部接口this.update=function(delta){updateQueue(delta);}timer的具体实现可以参考:https://github.com/leeenx/es6-utils#timertimerusedwithCreateJS://es6codeimporttimerfrom'./modules/timer';//统一tickercreatejs.Ticker.addEventListener("tick",function(e){e.paused||timer.update(e.delta);});计时器与PIXI一起使用://es6代码importtimerfrom'./modules/timer';//unifiedtickerapp.ticker.add("tick",function(){timer.update(app.ticker.elapsedMS);});原文链接:https://aotu.io/notes/2017/09/25/manage-setTimeout-an-setInterval/作者:leeenx【本文为专栏作者“凹凸实验室”原创稿件,转载请联系原文作者获得转载授权】点此查看该作者更多好文
