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 相关文章推荐
Locate a File Using a File Open Dialog Box
Jun 18 Javascript
JavaScript几种形式的树结构菜单
May 10 Javascript
浅析javascript中function 的 length 属性
May 27 Javascript
javascript 常见功能汇总
Jun 11 Javascript
微信支付如何实现内置浏览器的H5页面支付
Sep 25 Javascript
跟我学习javascript的prototype原型和原型链
Nov 18 Javascript
判断JS对象是否拥有某属性的方法推荐
May 12 Javascript
JSON 必知必会 观后记
Oct 27 Javascript
javascript内存分配原理实例分析
Apr 10 Javascript
手把手带你封装一个vue component第三方库
Feb 14 Javascript
微信小程序中如何使用flyio封装网络请求
Jul 03 Javascript
js实现简单的秒表
Jan 16 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
Eclipse中php插件安装及Xdebug配置的使用详解
2013/04/25 PHP
PHP的变量类型和作用域详解
2014/03/12 PHP
PHP使用pear实现mail发送功能 windows环境下配置pear
2016/04/15 PHP
CodeIgniter框架基本增删改查操作示例
2017/03/23 PHP
PHP的cookie与session原理及用法详解
2019/09/27 PHP
用javascript编写的第一人称射击游戏
2007/02/25 Javascript
Javascript中的数学函数
2007/04/04 Javascript
CSS常用网站布局实例
2008/04/03 Javascript
js 自定义的联动下拉框
2010/02/07 Javascript
formValidator3.3的ajaxValidator一些异常分析
2011/07/12 Javascript
非主流的textarea自增长实现js代码
2011/12/20 Javascript
解析Javascript小括号“()”的多义性
2013/12/03 Javascript
jQuery中常用的遍历函数用法实例总结
2015/09/01 Javascript
AngularJs bootstrap搭载前台框架——js控制部分
2016/09/01 Javascript
微信小程序 石头剪刀布实例代码
2017/01/04 Javascript
超全面的JavaScript开发规范(推荐)
2017/01/21 Javascript
jQuery实现的鼠标滚轮控制图片缩放功能实例
2017/10/14 jQuery
vue2 router 动态传参,多个参数的实例
2017/11/10 Javascript
基于vue-cli vue-router搭建底部导航栏移动前端项目
2018/02/28 Javascript
GOJS+VUE实现流程图效果
2018/12/01 Javascript
node事件循环和process模块实例分析
2020/02/14 Javascript
Python使用lxml模块和Requests模块抓取HTML页面的教程
2016/05/16 Python
python 性能提升的几种方法
2016/07/15 Python
编写多线程Python服务器 最适合基础
2018/09/14 Python
实时获取Python的print输出流方法
2019/01/07 Python
python开发之anaconda以及win7下安装gensim的方法
2019/07/05 Python
Python利用matplotlib绘制约数个数统计图示例
2019/11/26 Python
tensorflow 只恢复部分模型参数的实例
2020/01/06 Python
python 穷举指定长度的密码例子
2020/04/02 Python
python3+opencv 使用灰度直方图来判断图片的亮暗操作
2020/06/02 Python
Python中BeautifulSoup通过查找Id获取元素信息
2020/12/07 Python
Stutterheim瑞典:瑞典高级外套时装品牌
2019/06/24 全球购物
国际贸易个人求职信范文
2014/01/04 职场文书
呼啸山庄读书笔记
2015/06/29 职场文书
pytorch训练神经网络爆内存的解决方案
2021/05/22 Python
Python+Selenium自动化环境搭建与操作基础详解
2022/03/13 Python