setTimeout和setInterval的深入理解


Posted in Javascript onNovember 08, 2013

大概半年前发表过一篇关于setTimeout和setInterval的文章,但是现在回去仔细一看发现其实存在很多不足以及错误。事实上,setTimeout和setInterval并没有我们字面上理解的那么简单。要真正掌握并理解这两个方法,还得从javascript的单线程机制说起。

【开门见山】setTimeout和setInterval是如何工作的呢?
我们知道,js是单线程执行的。所以其实setTimeout和setInterval所谓的“异步调用”事实上是通过将代码段插入到代码的执行队列中实现的。

而如何计算插入的时间点呢?自然是要用到我们所说的timer,也就是计时器。当执行setTimeout和setInterval的时候,timer会根据你设定的时间“准确”地找到代码的插入点。当队列“正常”地执行到插入点时,就触发timer callback,也就是我们设定的回调函数:

function fn() { 
/* 
here is some codes 
*/ 
setTimeout(function() {alert('ok!')},1000); 
}

上面这个例子就是我们通常的用法,应该容易理解。可是,timer真的能那么准确么?代码队列的执行真的能那么正常么?

【斩草除根】重新认识所谓的“异步”
刚刚已经知道,事实上setTimeout和setInterval只是简简单单地通过插入代码到代码队列来实现代码的延迟执行(或者说异步执行)。但是事实上所谓的异步只是一个假象——它同样运行在一个线程上!
那么问题就来了,要是在代码插入点前的代码执行时间超过了传入setTimeout或setInterval的设定时间会怎样呢?让我们来看看这段代码:

function fn() { 
setTimeout(function(){alert('can you see me?');},1000); 
while(true) {} 
}

你觉得这段代码的执行结果是什么呢?答案是,alert永远不会出现。
这是为什么呢?因为,while这段代码没有执行完,插入在后面的代码便永远不会执行。
综上所述,其实JS终归是单线程产物。无论如何“异步”都不可能突破单线程这个障碍。所以许多的“异步调用”(包括Ajax)事实上也只是“伪异步”而已。只要理解了这么一个概念,也许理解setTimeout和setInterval也就不难了。
Javascript 相关文章推荐
javascript编程起步(第二课)
Jan 10 Javascript
jquery图片上下tab切换效果
Mar 18 Javascript
js事件冒泡实例分享(已测试)
Apr 23 Javascript
js的alert弹出框出现乱码解决方案
Sep 02 Javascript
js获取元素相对窗口位置的实现代码
Sep 28 Javascript
Bootstrap每天必学之简单入门
Nov 19 Javascript
js流动式效果显示当前系统时间
May 16 Javascript
JavaScript编程中实现对象封装特性的实例讲解
Jun 24 Javascript
谈谈jQuery之Deferred源码剖析
Dec 19 Javascript
javaScript中"=="和"==="的区别详解
Mar 16 Javascript
vue2.0项目实现路由跳转的方法详解
Jun 21 Javascript
vue-property-decorator用法详解
Dec 12 Javascript
如何获取select下拉框的值(option没有及有value属性)
Nov 08 #Javascript
jquery ajax修改全局变量示例代码
Nov 08 #Javascript
IE8下String的Trim()方法失效的解决方法
Nov 08 #Javascript
编写js扩展方法判断一个数组中是否包含某个元素
Nov 08 #Javascript
jquery滚动条插件jScrollPane的使用介绍
Nov 08 #Javascript
JQ获取动态加载的图片大小的正确方法分享
Nov 08 #Javascript
用JS将搜索的关键字高亮显示实现代码
Nov 08 #Javascript
You might like
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
2013/06/20 PHP
PHP 之 写时复制介绍(Copy On Write)
2014/05/13 PHP
PHP中header用法小结
2016/05/23 PHP
php通过文件头判断格式的方法
2016/05/28 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
基于jquery的一个简单的脚本验证插件
2010/04/05 Javascript
javascript实现日历控件(年月日关闭按钮)
2012/12/12 Javascript
兼容IE、firefox以及chrome的js获取时间(getFullYear)
2014/07/04 Javascript
JS平滑无缝滚动效果的实现代码
2016/05/06 Javascript
使用jquery获取url及url参数的简单实例
2016/06/14 Javascript
jQuery实现的网格线绘制方法
2016/06/20 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
深入理解选择框脚本[推荐]
2016/12/13 Javascript
nodejs redis 发布订阅机制封装实现方法及实例代码
2016/12/15 NodeJs
获取当前按钮或者html的ID名称实例(推荐)
2017/06/23 Javascript
详解Vue.js之视图和数据的双向绑定(v-model)
2017/06/23 Javascript
vue.js源代码core scedule.js学习笔记
2017/07/03 Javascript
Element UI 自定义正则表达式验证方法
2018/09/04 Javascript
three.js 如何制作魔方
2020/07/31 Javascript
Python的Django框架安装全攻略
2015/07/15 Python
python逆向入门教程
2018/01/15 Python
python将字典内容存入mysql实例代码
2018/01/18 Python
Python 一键制作微信好友图片墙的方法
2019/05/16 Python
Python使用字典实现的简单记事本功能示例
2019/08/15 Python
pandas DataFrame运算的实现
2020/06/14 Python
实例代码讲解Python 线程池
2020/08/24 Python
python软件测试Jmeter性能测试JDBC Request(结合数据库)的使用详解
2021/01/26 Python
css3的transition效果和transfor效果示例介绍
2013/10/30 HTML / CSS
Reebonz中国官网:新加坡奢侈品购物网站
2017/03/17 全球购物
公司员工的自我评价范例
2013/11/01 职场文书
党员干部批评与自我批评反四风思想汇报
2014/09/21 职场文书
党员个人整改措施
2014/10/24 职场文书
有关信念的名言语录集锦
2019/12/06 职场文书
web前端之css水平居中代码解析
2021/05/20 HTML / CSS
PyTorch 如何检查模型梯度是否可导
2021/06/05 Python
Python中的 enumerate和zip详情
2022/05/30 Python