loading

setTimeout 模拟 setInterval

# 为什么要用 setTimeout 模拟 setInterval

  • setInterval 会在指定的时间把函数添加到事件队列,而不是在指定的时间执行代码,这时如果事件队列中前面的定时器如果由于前面的任务队列存在耗时的操作,导致前一次的定时器函数还未执行或者执行完毕,就会导致这次的定时器函数被跳过,不会添加到宏任务事件队列,导致执行时间不准确
  • 如果 setInterval 定时器的函数中存在耗时的操作,也会导致执行时间不准确,甚至可能出现同时间执行两次的操作
  • 如果希望 setInterval 的执行时间是一个变量,满足条件后改变这个时间变量,这时会发现 setInterval 的执行时间还是最初的执行时间,不会改变;而 setTimeout 不存在这个问题

# 开始模拟

class SetInterval {
 tasks = [];

 // 添加定时
 add(name, callbabck, time = 0) {
     if(!name || !callback || typeof callback != `function`) return;
     this.tasks.push({
         name,
         callback,
         time
      })
     this.run(name);
 }

 // 开始定时
 run(name) {
     const _this = this;
     function inner() {
         const task = _this.tasks.find(item => item.name == name);
         if(!task) return;
         const timer = setTimeout(() => {
             task.callback();
             clearTimeout(timer)
             inner()
         }, task.time)
     }
     inner()
 }

 // 清除定时
 clear(name) {
     const taskIndex = this.tasks.findIndex(item => item.name == name)
     if(taskIndex != -1) {
         this.tasks.splice(taskIndex, 1);
     }
 }

 clearAll() {
     this.tasks = []
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
最近更新时间: 2021/06/17 10:13:36
最近更新
01
2023/07/03 00:00:00
02
2023/04/22 00:00:00
03
2023/02/16 00:00:00