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 相关文章推荐
仅img元素创建后不添加到文档中会执行onload事件的解决方法
Jul 31 Javascript
用JavaScript实现使用鼠标画线的示例代码
Aug 19 Javascript
JavaScript中计算网页中某个元素的位置
Jun 10 Javascript
原生js和jQuery实现淡入淡出轮播效果
Dec 25 Javascript
jQuery实现区域打印功能代码详解
Jun 17 Javascript
jquery选择器中的空格与大于号>、加号+与波浪号~的区别介绍
Jun 24 Javascript
深入学习 JavaScript中的函数调用
Mar 23 Javascript
Vue中引入样式文件的方法
Aug 18 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
Jan 05 Javascript
angularJs自定义过滤器实现手机号信息隐藏的方法
Oct 08 Javascript
JS实现checkbox互斥(单选)功能示例
May 04 Javascript
详解Vue项目的打包方式(生成dist文件)
Jan 18 Vue.js
如何获取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
PHP自动选择 连接本地还是远程数据库
2010/12/02 PHP
php多用户读写文件冲突的解决办法
2013/11/06 PHP
CI框架在CLI下执行占用内存过大问题的解决方法
2014/06/17 PHP
Zend Studio使用技巧两则
2016/04/01 PHP
PHP实现的统计数据功能详解
2016/12/06 PHP
Laravel框架实现的上传图片到七牛功能详解
2019/09/06 PHP
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
2015/08/15 Javascript
js实现图片轮播效果
2015/12/19 Javascript
Javascript复制实例详解
2016/01/28 Javascript
javascript的几种写法总结
2016/09/30 Javascript
jquery——九宫格大转盘抽奖实例
2017/01/16 Javascript
自定义vue组件发布到npm的方法
2018/05/09 Javascript
《javascript设计模式》学习笔记四:Javascript面向对象程序设计链式调用实例分析
2020/04/07 Javascript
[01:28]2014DOTA2国际邀请赛中国区预选赛四大豪门直升机抵达会场
2014/05/24 DOTA
解决Tensorflow使用pip安装后没有model目录的问题
2018/06/13 Python
使用Python实现文字转语音并生成wav文件的例子
2019/08/08 Python
Python3 venv搭建轻量级虚拟环境的步骤(图文)
2019/08/09 Python
python将字母转化为数字实例方法
2019/10/04 Python
python和pywin32实现窗口查找、遍历和点击的示例代码
2020/04/01 Python
Python气泡提示与标签的实现
2020/04/01 Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
2020/08/11 Python
python 如何对logging日志封装
2020/12/02 Python
使用Python封装excel操作指南
2021/01/29 Python
欧洲高端品牌直销店:Fashionesta
2016/08/31 全球购物
采用专利算法搜索最廉价的机票:CheapAir
2016/09/10 全球购物
西班牙香水和化妆品网上商店:Douglas
2017/10/29 全球购物
台湾最大银发乐活百货:乐龄网
2018/05/21 全球购物
2019年Java面试必问之经典试题
2012/09/12 面试题
办公室前台岗位职责
2014/01/04 职场文书
毕业生自荐书模版
2014/01/04 职场文书
优秀教师先进事迹材料
2014/12/15 职场文书
实习证明模板
2015/06/16 职场文书
队列队形口号
2015/12/25 职场文书
使用python将HTML转换为PDF pdfkit包(wkhtmltopdf) 的使用方法
2022/04/21 Python
HTML CSS 一个标签实现带动画的抖音LOGO
2022/04/26 HTML / CSS