相信你们对 setInterval
, setTimeout
两个 api 是熟悉得不能再熟悉了,它们是咱们经常使用的 web 定时器。javascript
const timer1 = setInteral(() => {
console.log(1)
}, 1000)
const timer1 = setTimeout(() => {
console.log(2)
}, 2000)
复制代码
值得注意的是咱们在建立的定时器不用以后最好清除掉。前端
clearInterval(timer1)
clearTimeout(timer2)
复制代码
那咱们今天来讨论一下,如何实现一个定时器呢?java
关于 setTimeout, 同事给出了这样的实现:git
逻辑也很是清晰,在函数内部构造一个循环堵住程序,等到时间到后跳出循环执行 callback,至关于开闸泄洪。es6
可是这样写确定是有问题的,咱们知道 js 的定时器是定义为宏任务的,在时间循环中是不会阻塞主线程运行的,所以这种是比较 hack 的作法,没有实现宏任务。所以这种是最早废弃的github
若是能够用 setInterval,setTimeout 相互实现的话,那咱们就有不少思路了web
个人 setTimeout 是这样实现的,经过 setInterval 构造一个定时器,到第一次执行时清除定时器,执行回调函数api
咱们看一下效果函数
执行结果以下:学习
咱们看到这里的定时器是没有阻碍主执行粘的,基本达到了咱们的目的
当咱们实现了定时器以后,还有一个问题,咱们的定时器是没法消除的,为了能够有添加定时器、清除定时器、清除所有定时器等操做,我决定经过 es6 的类来实现
思路中的大体结构是这样,咱们维护一个定时器栈,这个类有 add,run,clear,clearAll 等方法,能够添加,清除,运行定时器,有了这个思路以后咱们一步一步来实现
原理很简单,添加定时器就是直接把数据推入咱们的栈中,推入前须要作一下简单的数据校验
经过 name 在栈中查找,找到对应的定时器以后执行,这里须要用到 setTimeout 来实现 setInterval,执行方式和上面同样。
原理就是找到对应的定时器,在栈中删掉,这样在 run 的递归函数中找不到对应的定时器就没法执行。清除所有定时器直接清空栈就好。
到这里咱们实现了一个简单的 setInterval
咱们来看一下效果:
能够看到 4.5s 以后定时器被清除了
到这里咱们就实现了一个简单的定时器,你能够写一个 本身的 setTimeout 吗?
关注 前端 100 问,一块儿学习,持续扩展中