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实例收集(20个)
Apr 21 Javascript
javascript 防止刷新,后退,关闭
Aug 07 Javascript
MooTools 页面滚动浮动层智能定位实现代码
Aug 23 Javascript
Function.prototype.bind用法示例
Sep 16 Javascript
JQuery 图片滚动轮播示例代码
Mar 24 Javascript
javascript实现的固定位置悬浮窗口实例
Apr 30 Javascript
纯JS代码实现气泡效果
May 04 Javascript
原生js获取left值和top值的三种方法
Aug 02 Javascript
React/Redux应用使用Async/Await的方法
Nov 16 Javascript
解决v-for中使用v-if或者v-bind:class失效的问题
Sep 25 Javascript
深入学习Vue nextTick的用法及原理
Oct 08 Javascript
ES6 十大特性简介
Dec 09 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作为网站开发语言的原因分享
2012/01/03 PHP
php中使用cookie来保存用户登录信息的实现代码
2012/03/08 PHP
PHP中对缓冲区的控制实现代码
2013/09/29 PHP
一键生成各种尺寸Icon的php脚本(实例)
2017/02/08 PHP
用于自动添加Digg This!按钮的JavaScript
2006/12/23 Javascript
国外Lightbox v2.03.3 最新版 下载
2007/10/17 Javascript
javascript学习笔记(六) Date 日期类型
2012/06/19 Javascript
JS对象转换为Jquery对象实现代码
2013/12/29 Javascript
jquery 新建的元素事件绑定问题解决方案
2014/06/12 Javascript
jQuery修改li下的样式以及li下的img的src的值的方法
2014/11/02 Javascript
Jquery AJAX POST与GET之间的区别详细介绍
2016/10/17 Javascript
预防网页挂马的方法总结
2016/11/03 Javascript
vue.js学习之vue-cli定制脚手架详解
2017/07/02 Javascript
JS中定位 position 的使用实例代码
2017/08/06 Javascript
AngularJS 中ui-view传参的实例详解
2017/08/25 Javascript
加载 vue 远程代码的组件实例详解
2017/11/20 Javascript
vue cli 全面解析
2018/02/28 Javascript
小程序图片剪裁加旋转的示例代码
2018/07/10 Javascript
vue 1.0 结合animate.css定义动画效果
2018/07/11 Javascript
微信小程序获取音频时长与实时获取播放进度问题
2018/08/28 Javascript
微信小程序环境下将文件上传到OSS的方法步骤
2019/05/31 Javascript
vue中路由跳转不计入history的操作
2020/09/21 Javascript
Python爬虫爬验证码实现功能详解
2016/04/14 Python
Python 爬虫模拟登陆知乎
2016/09/23 Python
零基础使用Python读写处理Excel表格的方法
2019/05/02 Python
Django中间件基础用法详解
2019/07/18 Python
Python面向对象实现方法总结
2020/08/12 Python
pandas统计重复值次数的方法实现
2021/02/20 Python
HTML5 Canvas的性能提高技巧经验分享
2013/07/02 HTML / CSS
企业总经理职责
2014/02/02 职场文书
监察建议书范文
2014/03/12 职场文书
继承公证书样本
2014/04/04 职场文书
优秀护士先进事迹
2014/05/08 职场文书
政协会议宣传标语
2014/10/09 职场文书
2015年工程部工作总结
2015/04/30 职场文书
你有一份《诚信考试承诺书》待领取
2019/11/13 职场文书