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的textarea发布框限制文字字数输入(添加中文识别)
Feb 16 Javascript
jQuery-serialize()输出序列化form表单值的方法
Dec 26 Javascript
原生js结合html5制作简易的双色子游戏
Mar 30 Javascript
JS动态显示表格上下frame的方法
Mar 31 Javascript
javasript实现密码的隐藏与显示
May 08 Javascript
如何使用Bootstrap创建表单
Mar 29 Javascript
AngularJS封装$http.post()实例详解
May 06 Javascript
在vue.js中抽出公共代码的方法示例
Jun 08 Javascript
浅谈node中的exports与module.exports的关系
Aug 01 Javascript
vue-resource请求实现http登录拦截或者路由拦截的方法
Jul 11 Javascript
解决layer.confirm选择完之后消息框不消失的问题
Sep 16 Javascript
vue仿淘宝滑动验证码功能(样式模仿)
Dec 10 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 htmlentities和htmlspecialchars 的区别
2008/08/18 PHP
ThinkPHP使用PHPExcel实现Excel数据导入导出完整实例
2014/07/22 PHP
PHP内核探索之解释器的执行过程
2015/12/22 PHP
PHP生成静态HTML文档实现代码
2016/06/23 PHP
Laravel 自动生成验证的实例讲解:login / logout
2019/10/14 PHP
Javascript 键盘事件的组合使用实现代码
2012/05/04 Javascript
S2SH整合JQuery+Ajax实现登录验证功能实现代码
2013/01/30 Javascript
js实现可得到不同颜色值的颜色选择器实例
2015/02/28 Javascript
JavaScript实现简单Tip提示框效果
2016/04/20 Javascript
Angular4编程之表单响应功能示例
2017/12/13 Javascript
react中fetch之cors跨域请求的实现方法
2018/03/14 Javascript
JS实现左边列表移到到右边列表功能
2018/03/28 Javascript
JS实现的简单折叠展开动画效果示例
2018/04/28 Javascript
微信小程序实现之手势锁功能实例代码
2018/07/19 Javascript
jquery插件开发模式实例详解
2019/07/20 jQuery
vue ssr+koa2构建服务端渲染的示例代码
2020/03/23 Javascript
vue 输入电话号码自动按3-4-4分割功能的实现代码
2020/04/30 Javascript
js实现删除json中指定的元素
2020/09/22 Javascript
浅谈JSON5解决了JSON的两大痛点
2020/12/14 Javascript
[02:23]2014DOTA2国际邀请赛中国战队回顾
2014/08/01 DOTA
[01:36:17]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第一场 1月31日
2021/03/11 DOTA
python通过urllib2获取带有中文参数url内容的方法
2015/03/13 Python
python中随机函数random用法实例
2015/04/30 Python
python http接口自动化脚本详解
2018/01/02 Python
如何利用Python分析出微信朋友男女统计图
2019/01/25 Python
python自动结束mysql慢查询会话的实例代码
2019/10/27 Python
python_mask_array的用法
2020/02/18 Python
使用JS+CSS3技术:让你的名字动起来
2013/04/27 HTML / CSS
Trip.com澳大利亚:在线旅行社
2019/12/01 全球购物
平民服装店创业计划书
2014/01/17 职场文书
就业自我评价
2014/02/04 职场文书
军人违纪检讨书
2014/02/04 职场文书
手术室护士长竞聘书
2014/03/31 职场文书
乡镇爱国卫生月活动总结
2014/06/25 职场文书
开展读书活动总结
2014/06/30 职场文书
gateway与spring-boot-starter-web冲突问题的解决
2021/07/16 Java/Android