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 相关文章推荐
jQuery阻止同类型事件小结
Apr 19 Javascript
深入理解JQuery keyUp和keyDown的区别
Dec 12 Javascript
javascript处理a标签超链接默认事件的方法
Jun 29 Javascript
js鼠标点击按钮切换图片-图片自动切换-点击左右按钮切换特效代码
Sep 02 Javascript
js当前页面登录注册框,固定div,底层阴影的实例代码
Oct 04 Javascript
[原创]javascript typeof id==='string'?document.getElementById(id):id解释
Nov 02 Javascript
微信小程序-横向滑动scroll-view隐藏滚动条
Apr 20 Javascript
ztree简介_动力节点Java学院整理
Jul 19 Javascript
Vue 进入/离开动画效果
Dec 26 Javascript
JavaScript使用math.js进行精确计算操作示例
Jun 19 Javascript
angular 实时监听input框value值的变化触发函数方法
Aug 31 Javascript
JS实现的对象去重功能示例
Jun 04 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
我的论坛源代码(十)
2006/10/09 PHP
PHP编程之高级技巧——利用Mysql函数
2006/10/09 PHP
PHPEXCEL 使用小记
2013/01/06 PHP
利用中国天气预报接口实现简单天气预报
2014/01/20 PHP
PHP实现路由映射到指定控制器
2016/08/13 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
jQuery 使用个人心得
2009/02/26 Javascript
让人期待的2011年度最佳 jQuery 插件分享
2012/03/16 Javascript
使用jquery.qrcode生成彩色二维码实例
2014/08/08 Javascript
浅谈Jquery核心函数
2015/06/18 Javascript
javascript电商网站抢购倒计时效果实现
2015/11/19 Javascript
Javascript操作dom对象之select全面解析
2017/04/24 Javascript
百度地图去掉marker覆盖物或者去掉maker的label文字方法
2018/01/26 Javascript
React中的render何时执行过程
2018/04/13 Javascript
React路由管理之React Router总结
2018/05/10 Javascript
JS实现字符串翻转的方法分析
2018/08/31 Javascript
vue-cli 2.*中导入公共less文件的方法步骤
2018/11/22 Javascript
json数据格式常见操作示例
2019/06/13 Javascript
Angular 多级路由实现登录页面跳转(小白教程)
2019/11/19 Javascript
vue实现鼠标移过出现下拉二级菜单功能
2019/12/12 Javascript
小程序开发之模态框组件封装
2020/04/23 Javascript
[52:14]VG vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python中的ctime()方法使用教程
2015/05/22 Python
Python编写电话薄实现增删改查功能
2016/05/07 Python
磁盘垃圾文件清理器python代码实现
2020/08/24 Python
浅析PyTorch中nn.Linear的使用
2019/08/18 Python
Python基础教程之输入输出和运算符
2020/07/26 Python
Ubuntu16安装Python3.9的实现步骤
2020/12/15 Python
python matplotlib工具栏源码探析二之添加、删除内置工具项的案例
2021/02/25 Python
城野医生官方海外旗舰店:风靡亚洲毛孔收敛水
2018/04/26 全球购物
介绍一下Ruby的特点
2013/01/20 面试题
制药工程专业个人求职自荐信
2014/01/25 职场文书
文员岗位职责范本
2014/03/08 职场文书
生物科学专业自荐书
2014/06/20 职场文书
2014党员批评和自我批评思想汇报
2014/09/21 职场文书
演讲比赛主持词
2015/06/29 职场文书