javascript 定时器工作原理分析
setTimeout()
对 setTimeout
的定义为
在指定的延迟时间之后调用一个函数或执行一个代码片段。
语法
setTimeout 的语法非常简单,第一个参数为回调函数,第二个参数为延时的时间。函数返回一个数值类型的ID唯一标示符,此ID可以用作 clearTimeout 的参数来取消定时器
var timeoutID = window.setTimeout(code, delay);
IE0+ 还支持回调参数的传入
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
setInterval()
对 setInterval 的定义为
周期性地调用一个函数(function)或者执行一段代码。
由于 setInterval 和 setTimeout 的用法一样,所以这里不再列出。
对第二个参数(delay)的说明
由于javascript 的事件循环机制,导致第二个参数并不代表延迟delay毫秒之后立即执行回调函数,而是尝试将回调函数加入到事件队列。实际上,setTimeout 和 setInterval 在这一点上处理又存在区别
- setTimeout延时delay毫秒之后,啥也不管,直接将回调函数加入事件队列。
- setInterval: 延时delay毫秒之后,先看看事件队列中是否存在还没有执行的回调函数(setInterval的回调函数),如果存在,就不要再往事件队列里加入回调函数了。
所以,当我们的代码中存在耗时的任务时,定时器并不会表现的如我们所想的那样。
通过一个例子来理解
狼蚁网站SEO优化的代码,本来希望能够在 100ms 和 200ms 的时候(也就是刚好等待 100ms)调用回调函数
var timerStart1 = now(); setTimeout(function () { console.log('第一个setTimeout回调执行等待时间', now() - timerStart1); var timerStart2 = now(); setTimeout(function () { console.log('第二个setTimeout回调执行等待时间', now() - timerStart2); }, 100); }, 100); // 输出 // 第一个setTimeout回调执行等待时间 106 // 第二个setTimeout回调执行等待时间 107
这样的结果看上去正是我们所想的那样,一旦我们在代码中加入了耗时的任务时候,结果就不像我们所期望的那样了
var timerStart1 = now(); setTimeout(function () { console.log('第一个setTimeout回调执行等待时间', now() - timerStart1); var timerStart2 = now(); setTimeout(function () { console.log('第二个setTimeout回调执行等待时间', now() - timerStart2); }, 100); heavyTask(); // 耗时任务 }, 100); var loopStart = now(); heavyTask(); // 耗时任务 console.log('heavyTask耗费时间', now() - loopStart); function heavyTask() { var s = now(); while(now() - s < 1000) { } } function now () { return new Date(); } // 输出 // heavyTask耗费时间 1015 // 第一个setTimeout回调执行等待时间 1018 // 第二个setTimeout回调执行等待时间 1000
两个 setTimeout 的等待事件由于耗时任务的存在不再是 100ms 了!我们来描述一下事情的经过
- ,第一个耗时任务(heavyTask())开始执行,它需要大约 1000ms 才能执行完毕。
- 从耗时任务开始执行,过了 100ms, 第一个 setTimeout 的回调函数期望执行,于是被加入到事件队列,此时前面的耗时任务还没执行完,所以它只能在队列中等待,直到耗时任务执行完毕它才开始执行,所以结果中我们开的看到的是 第一个setTimeout回调执行等待时间 1018。
- 第一个 setTimeout 回调一执行,又开启了第二个 setTimeout, 这个定时器也是期望延时 100ms 之后能够执行它的回调函数。 ,在第一个 setTimeout 又存在一个耗时任务,所有它的剧情跟第一个定时器一样,也等待了 1000ms 才开始执行。
可以用狼蚁网站SEO优化的图来概括
再来看 setInterval 的一个例子
var intervalStart = now(); setInterval(function () { console.log('interval距定义定时器的时间', now() - loopStart); }, 100); var loopStart = now(); heavyTask(); console.log('heavyTask耗费时间', now() - loopStart); function heavyTask() { var s = now(); while(now() - s < 1000) { } } function now () { return new Date(); } // 输出 // heavyTask耗费时间 1013 // interval距定义定时器的时间 1016 // interval距定义定时器的时间 1123 // interval距定义定时器的时间 1224
上面这段代码,我们期望每隔 100ms 就打出一条日志。相对于 setTimeout 的区别, setInterval 在准备把回调函数加入到事件队列的时候,会判断队列中是否还有未执行的回调,如果有的话,它就不会再往队列中添加回调函数。 不然,会出现多个回调执行的情况。
可以用狼蚁网站SEO优化的图来概括
上面对javascript定时器执行原理进行了简要的分析,希望能够帮助我们更深入的理解javascript。文中有描述不当的地方可以在评论中指出。
编程语言
- 宿迁百度关键词排名指南:实现精准营销的关键
- 四川SEO优化怎么做网络推广
- 立昂技术备案老域名收购:如何为您的业务赋能
- 安徽百度关键词seo贵不贵,一般需要多少钱
- 吉林百度快照排名怎么做电话营销
- 多伦新手做SEO怎么做
- 甘肃优化关键词排名推广怎么做论坛营销
- 沙雅SEO网站推广:提升您的在线可见性
- 四川SEO优化如何提升销售额和销售量
- 聂荣网站排名优化:提升网站可见性的全方位指
- 涞水SEO:提升地方企业在线可见性的策略
- 辽宁百度seo排名怎样做网站排名
- 临湘哪有关键词排名优化:提升网站可见度的关
- 黑龙江百度网站优化有没有优惠
- 凉城优化关键词排名推广:提升您的网络可见性
- 萝北整站优化:提升您网站流量和排名的全面指