开发中常常使用setTimeout进行一些延迟操做。昨天忽然想了解下setTimeout的handler到底在队列中的什么位置特别好奇。今天特意来测试下。javascript
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。html
setTimeout(code,millisec)
参数 | 描述 |
---|---|
code | 必需。要调用的函数后要执行的 JavaScript 代码串。 |
millisec | 必需。在执行代码前需等待的毫秒数。 |
提示:setTimeout() 只执行 code 一次。若是要屡次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout()。java
以上定义来源于w3school.comajax
先了解下浏览器,浏览器是多线程的。浏览器
JS运行在浏览器中,是单线程的,每一个window一个JS引擎线程。既然是单线程的,的在某个特定的时刻只有特定代码能被执够行,并阻塞其它的代码。(至于ajax的实现这里就不说了。)多线程
来了解下setTimeout的简单的原理:异步
setTimeout调用的时候,JavaScript引擎会启动定时器timer,大约millisec(ms)之后执行code,当定时器时间到,就把该事件放到主事件队列等待处理。函数
注意:学习
浏览器JavaScript线程空闲的时候才会真正执行测试
为何呢?由于当JavaScript线程的正在出来其余JavaScript代码时,其实以已经阻塞了其余的代码,其中包括的setTimeout的定时器部分的实现。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script type="text/javascript">
function testHandler() { console.log("调用了setTimeout的函数"); } window.onload = function () { console.log("开始"); console.log("设置setTimeout 100ms"); setTimeout(testHandler,100); console.log("休眠1000ms"); sleep(1000); testNext(); console.log("结束"); } function testNext() { console.log("后续执行的函数"); } function sleep(number) { var now = new Date(); var exitTime = now.getTime() + number; while (true) { now = new Date(); if (now.getTime() > exitTime) return; } } </script>
</head>
<body>
</body>
</html>
最终浏览器输出的结果:
此处setTimeout其实只延迟了100ms。而进setTimeout到结束中先模拟休眠了2000ms,而后再执行了testNext函数。可是从测试结果来看实际上testHandler倒是在整个队列的最后。这就解释了上诉中说的,setTimeout将code加入到队列的操做必须是在线程空闲的时候才会执行了。
上诉测试发现,实际应用中。setTimeout的millisec参数无论你设置多少,实际执行都是在线程的最后,由于在执行一个操做的时候,JavaScript确定是一直把代码执行完后再走setTimeout绑定的code的。
那么问题来了。setTimeout(handler,0)和setTimeout(handler,100)在单独使用时,好像并无区别。(中间执行的代码处理时间超过100ms时)
<script type="text/javascript">
function testHandler() { console.log("调用了setTimeout的函数"); } window.onload = function () { console.log("开始"); console.log("设置setTimeout 100ms"); setTimeout(testHandler,100); setTimeout(function () { console.log("调用了setTimeout的函数2"); }, 50); console.log("休眠1000ms"); sleep(1000); testNext(); console.log("结束"); } function testNext() { console.log("后续执行的函数"); } function sleep(number) { var now = new Date(); var exitTime = now.getTime() + number; while (true) { now = new Date(); if (now.getTime() > exitTime) return; } } </script>
输出结果:
我的认为millisec通常在多个setTimeout一块儿使用的时,须要区分哪一个先加入到队列的时候才有用,不然均可以设置成setTimeout(handler,0)(异步操做不在讨论范围内)
以上哪有写的不对的地方欢迎指正学习。^3^
欢迎转载
转载注明原创地址:http://www.cnblogs.com/Jersen/p/4887225.html