最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

javascript定时器工作原理

来源:懂视网 责编:小采 时间:2020-11-27 20:25:39
文档

javascript定时器工作原理

javascript定时器工作原理:说到 javascript 中的定时器,我们肯定会想到 setTimeout() 和 setInterval() 这两个函数。本文将从事件循环(Event Loop) 的角度来分析两者的工作原理和区别。 setTimeout() MDN对 setTimeout 的定义为:在指定的延迟时间之后调用一个函数或执行
推荐度:
导读javascript定时器工作原理:说到 javascript 中的定时器,我们肯定会想到 setTimeout() 和 setInterval() 这两个函数。本文将从事件循环(Event Loop) 的角度来分析两者的工作原理和区别。 setTimeout() MDN对 setTimeout 的定义为:在指定的延迟时间之后调用一个函数或执行
  说到 javascript 中的定时器,我们肯定会想到 setTimeout() 和 setInterval() 这两个函数。本文将从事件循环(Event Loop) 的角度来分析两者的工作原理和区别。

 setTimeout()

  MDN对 setTimeout 的定义为:

在指定的延迟时间之后调用一个函数或执行一个代码片段。

  语法

  setTimeout 的语法非常简单,第一个参数为回调函数,第二个参数为延时的时间。函数返回一个数值类型的ID唯一标示符,此ID可以用作 clearTimeout 的参数来取消定时器:

var timeoutID = window.setTimeout(code, delay);

  IE0+ 还支持回调参数的传入:

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

 setInterval()

  MDN 对 setInterval 的定义为:

周期性地调用一个函数(function)或者执行一段代码。

  由于 setInterval 和 setTimeout 的用法一样,所以这里不再列出。

 对第二个参数(delay)的说明

  由于javascript 的事件循环机制,导致第二个参数并不代表延迟delay毫秒之后立即执行回调函数,而是尝试将回调函数加入到事件队列。实际上,setTimeout 和 setInterval 在这一点上处理又存在区别:

setTimeout:延时delay毫秒之后,啥也不管,直接将回调函数加入事件队列。

setInterval: 延时delay毫秒之后,先看看事件队列中是否存在还没有执行的回调函数(setInterval的回调函数),如果存在,就不要再往事件队列里加入回调函数了。

  所以,当我们的代码中存在耗时的任务时,定时器并不会表现的如我们所想的那样。

 通过一个例子来理解

  下面的代码,本来希望能够在 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 才开始执行。

  可以用下面的图来概括:

javascript 定时器工作原理

  再来看 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 在准备把回调函数加入到事件队列的时候,会判断队列中是否还有未执行的回调,如果有的话,它就不会再往队列中添加回调函数。 不然,会出现多个回调同时执行的情况。

  可以用下面的图来概括:

javascript 定时器工作原理

总结

上面对javascript定时器执行原理进行了简要的分析,希望能够帮助我们更深入的理解javascript。文中有描述不当的地方可以在评论中指出。

更多javascript 定时器工作原理相关文章请关注PHP中文网!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

javascript定时器工作原理

javascript定时器工作原理:说到 javascript 中的定时器,我们肯定会想到 setTimeout() 和 setInterval() 这两个函数。本文将从事件循环(Event Loop) 的角度来分析两者的工作原理和区别。 setTimeout() MDN对 setTimeout 的定义为:在指定的延迟时间之后调用一个函数或执行
推荐度:
标签: 工作 原理 计时器
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top