当前位置:网站首页>用setTimeout模拟setInterval定时器
用setTimeout模拟setInterval定时器
2022-07-25 15:06:00 【深海蓝山】
首先说明一点:定时器指定的时间间隔,表示的是何时将定时器的代码添加到消息队列,而不是何时执行代码。所以真正何时执行代码的时间是不能保证的,取决于何时被主线程的事件循环取到,并执行。
1.setTimeout()
setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器
var timerId = setTimeout(func|code, delay);
clearTimeout(timerId);//取消定时器
setTimeout函数接受两个参数,第一个参数func|code是将要推迟执行的函数名或者一段代码,第二个参数delay是推迟执行的毫秒数
2.setInterval()
setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执触发一次,也就是无限次的定时执行
var i = 1
var timer = setInterval(function() {
console.log(i);
i++;
if(i>4){
clearInterval(timer);//取消定时器
}
}, 1000)
上面代码中,每隔1000毫秒就输出一个i的值,会无限运行下去,直到关闭当前窗口。
setInterval指定的是“开始执行”之间的间隔,并不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间。比如,setInterval指定每 1000ms 执行一次,每次执行需要 500ms,那么第一次执行结束后500毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要1200毫秒,那么它结束后,下一次执行就会立即开始。
setInterval还有一个特点,仅当队列中没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。
sleep(2000);
function sleep(ms) {
var start = Date.now();
while ((Date.now() - start) < ms) {
}
}
let i = 1;
var st = Date.now();
let timer = setInterval(function () {
if (i > 4) {
clearInterval(timer);
}
if (i == 2) {
sleep(500);//第二执行500ms,所以第二次执行结束后500ms就执行了第三次
}
if(i==4){
sleep(1200);//第四次延迟1200ms,超过了1000ms的间隔,所以第四次执行后马上就执行了第五次,第四、五次的执行时间是一样的
}
console.log(i, Date.now() - st);
i++;
}, 1000)

综上所述,setInterval 有两个缺点:
- 可能多个定时器连续执行
- 某些间隔会被跳过
为了确保两次执行之间有固定的间隔,一般使用setTimeout 模拟 setInterval 来规避它所带来的问题。
常见的实现如下:
let timer = null;
interval(func, wait){
let interv = function(){
func.call(null);
timer=setTimeout(interv, wait);
};
timer= setTimeout(interv, wait);
}模拟实现说明:
var i = 1;
var st = Date.now();
var timer = setTimeout(function f() {
if (i > 5) {
window.clearSetTimeout(timer);
} else {
if (i == 2) {
sleep(500);
}
if (i == 4) {
sleep(1200);
}
console.log(i, Date.now() - st);
i++;
timer = setTimeout(f, 1000);
}
}, 1000);
上面代码可以确保,下一次执行总是在本次执行结束之后的1000毫秒开始。
1 1000
settimeout.html:93 2 2501
settimeout.html:83 [Violation] 'setTimeout' handler took 499ms
settimeout.html:93 3 3501
settimeout.html:93 4 5707
settimeout.html:83 [Violation] 'setTimeout' handler took 1203ms
settimeout.html:93 5 6708
3.运行机制
setTimeout和setInterval的运行机制,是将指定的代码移出本轮事件循环,等到下一轮事件循环,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就继续等待。
这意味着,setTimeout和setInterval指定的回调函数,必须等到本轮事件循环的所有同步任务都执行完,才会开始执行。由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证,setTimeout和setInterval指定的任务,一定会按照预定时间执行。
4.setTimeout(f, 0)
setTimeout的作用是将代码推迟到指定时间执行,如果指定时间为0,即setTimeout(f, 0),也不会立即执行。必须要等到当前脚本的同步任务,全部处理完以后,才会执行setTimeout指定的回调函数f。也就是说,setTimeout(f, 0)会在下一轮事件循环一开始就执行。
setTimeout(f, 0)有几个非常重要的用途。它的一大应用是,可以调整事件的发生顺序。
边栏推荐
- CMake指定OpenCV版本
- 51 single chip microcomputer learning notes (2)
- 没错,请求DNS服务器还可以使用UDP协议
- Reprint ---- how to read the code?
- "How to use" decorator mode
- [comprehensive pen test] difficulty 4/5, classic application of line segment tree for character processing
- Overview of cloud security technology development
- 基于AMD EPYC服务器的EDA芯片设计解决方案
- easygui使用的语法总结
- String type time comparison method with error string.compareto
猜你喜欢
随机推荐
39 简洁版小米侧边栏练习
LeetCode_字符串_中等_151.颠倒字符串中的单词
剑指Offer | 二进制中1的个数
[C题目]牛客 链表中倒数第k个结点
Thymeleaf notes
"Ask every day" what is volatile
Spark parameter adjustment and tuning
SublimeText-win10光标跟随问题
Stored procedure bias of SQL to LINQ
"How to use" agent mode
44 Sina navigation, Xiaomi sidebar exercise
39 simple version of millet sidebar exercise
Fast-lio: fast and robust laser inertial odometer based on tightly coupled IEKF
给VS2010自动设置模板,加头注释
Overview of cloud security technology development
32 use of chrome debugging tools
了解一下new的过程发生了什么
C#,C/S升级更新
Yarn: the file yarn.ps1 cannot be loaded because running scripts is prohibited on this system.
Login of MySQL [database system]









