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 相关文章推荐
关于js日期转化为毫秒数“节省20%的效率和和节省9个字符“问题
Mar 01 Javascript
node.js 一个简单的页面输出实现代码
Mar 07 Javascript
定义JavaScript二维数组采用定义数组的数组来实现
Dec 09 Javascript
jQuery的$.proxy()应用示例介绍
Apr 03 Javascript
用jquery.sortElements实现table排序
May 04 Javascript
深入剖析JavaScript编程中的对象概念
Oct 21 Javascript
jQuery实现图片预加载效果
Nov 27 Javascript
js控制li的隐藏和显示实例代码
Oct 15 Javascript
微信小程序 获取当前地理位置和经纬度实例代码
Dec 05 Javascript
JavaScript实现垂直滚动条效果
Jan 18 Javascript
详解js中的原型,原型对象,原型链
Jul 16 Javascript
Openlayers实现点闪烁扩散效果
Sep 24 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
浅谈PHP 闭包特性在实际应用中的问题
2009/10/30 PHP
PHP Swoole异步读取、写入文件操作示例
2019/10/24 PHP
什么是JavaScript
2009/08/13 Javascript
使用jQuery轻松实现Ajax的实例代码
2010/08/16 Javascript
js实现仿MSN带关闭功能的右下角弹窗代码
2015/09/04 Javascript
JavaScript操作URL的相关内容集锦
2015/10/29 Javascript
jQuery自定义数值抽奖活动代码
2016/06/11 Javascript
基于BootStrap实现局部刷新分页实例代码
2016/08/08 Javascript
详解js运算符单竖杠“|”与“||”的用法和作用介绍
2016/11/04 Javascript
jQuery模拟窗口抖动效果
2017/03/15 Javascript
JS图片轮播与索引变色功能实例详解
2017/07/06 Javascript
jQuery 中msgTips 顶部弹窗效果实现代码
2017/08/14 jQuery
使用FileReader API创建Vue文件阅读器组件
2018/04/03 Javascript
Angular搜索场景中使用rxjs的操作符处理思路
2018/05/30 Javascript
Angular6中使用Swiper的方法示例
2018/07/09 Javascript
Node.js 实现抢票小工具 & 短信通知提醒功能
2019/10/22 Javascript
浅析JavaScript预编译和暗示全局变量
2020/09/03 Javascript
react项目从新建到部署的实现示例
2021/02/19 Javascript
从CentOS安装完成到生成词云python的实例
2017/12/01 Python
python生成不重复随机数和对list乱序的解决方法
2018/04/09 Python
python2与python3共存问题的解决方法
2018/09/18 Python
python查看模块安装位置的方法
2018/10/16 Python
详解从Django Rest Framework响应中删除空字段
2019/01/11 Python
python实现爬取百度图片的方法示例
2019/07/06 Python
python3.7 利用函数os pandas利用excel对文件名进行归类
2019/09/29 Python
Python列表list操作相关知识小结
2020/01/29 Python
DataFrame.groupby()所见的各种用法详解
2020/06/14 Python
python装饰器代码深入讲解
2021/03/01 Python
让IE下支持Html5的placeholder属性的插件
2014/09/02 HTML / CSS
解释i节点在文件系统中的作用
2013/11/26 面试题
授权委托书格式
2014/07/31 职场文书
部门活动策划方案
2014/08/16 职场文书
教师党的群众路线对照检查材料
2014/09/24 职场文书
社区党的群众路线教育实践活动总结材料
2014/10/31 职场文书
PyTorch 如何自动计算梯度
2021/05/23 Python
Python实现视频自动打码的示例代码
2022/04/08 Python