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 相关文章推荐
javascript 新浪背投广告实现代码
Jul 07 Javascript
extjs 列表框(multiselect)的动态添加列表项的方法
Jul 31 Javascript
JS保留两位小数 四舍五入函数的小例子
Nov 20 Javascript
js实现点击左右按钮轮播图片效果实例
Jan 29 Javascript
在Linux系统中搭建Node.js开发环境的简单步骤讲解
Jan 26 Javascript
jQuery技巧之让任何组件都支持类似DOM的事件管理
Apr 05 Javascript
微信小程序 地图map详解及简单实例
Jan 10 Javascript
关于js对textarea换行符的处理方法浅析
Aug 03 Javascript
微信小程序基于picker实现级联菜单
Feb 15 Javascript
JS实现在线ps功能详解
Jul 31 Javascript
微信公众号生成新浪短网址的实现(快速生成)
Aug 18 Javascript
antd vue 刷新保留当前页面路由,保留选中菜单,保留menu选中操作
Aug 06 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
php4的session功能评述(三)
2006/10/09 PHP
一些php技巧与注意事项分析
2011/02/03 PHP
Zend Framework教程之Application用法实例详解
2016/03/14 PHP
浅析Yii2 GridView实现下拉搜索教程
2016/04/22 PHP
JQuery 写的个性导航菜单
2009/12/24 Javascript
jquery 笔记 事件
2011/11/02 Javascript
基于jquery实现的鼠标悬停提示案例
2016/12/11 Javascript
Node.JS中事件轮询(Event Loop)的解析
2017/02/25 Javascript
基于Node.js的WebSocket通信实现
2017/03/11 Javascript
jQuery接受后台传递的List的实例详解
2017/08/02 jQuery
vue-cli的build的文件夹下没有dev-server.js文件配置mock数据的方法
2019/04/17 Javascript
js实现超级玛丽小游戏
2020/03/18 Javascript
Vue生命周期activated之返回上一页不重新请求数据操作
2020/07/26 Javascript
vue3+typescript实现图片懒加载插件
2020/10/26 Javascript
vue element和nuxt的使用技巧分享
2021/01/14 Vue.js
[02:35]DOTA2英雄基础教程 末日使者
2013/12/04 DOTA
[01:45]亚洲邀请赛互动指南虚拟物品介绍
2015/01/30 DOTA
Python中使用copy模块实现列表(list)拷贝
2015/04/14 Python
Python中用max()方法求最大值的介绍
2015/05/15 Python
Python机器学习之决策树算法实例详解
2017/12/06 Python
matplotlib.pyplot画图 图片的二进制流的获取方法
2018/05/24 Python
opencv python 图像去噪的实现方法
2018/08/31 Python
python 实现提取某个索引中某个时间段的数据方法
2019/02/01 Python
python3.6生成器yield用法实例分析
2019/08/23 Python
Django接收照片储存文件的实例代码
2020/03/07 Python
英国排名第一的礼品体验公司:Red Letter Days
2018/08/16 全球购物
Mountain Warehouse德国官网:英国户外零售商
2019/08/11 全球购物
高中军训感想800字
2014/02/23 职场文书
2014年小学德育工作总结
2014/12/05 职场文书
2014年房产经纪人工作总结
2014/12/08 职场文书
2015年基层党建工作汇报材料
2015/06/25 职场文书
2016年小学圣诞节活动总结
2016/03/31 职场文书
八年级地理课件资料及考点知识分享
2019/08/30 职场文书
go xorm框架的使用
2021/05/22 Golang
golang生成vcf通讯录格式文件详情
2022/03/25 Golang
Oracle 多表查询基本语法实例
2022/04/18 Oracle