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 css styleFloat和cssFloat
Mar 15 Javascript
XML文件转化成NSData对象的方法
Aug 12 Javascript
D3.js中data(), enter() 和 exit()的问题详解
Aug 17 Javascript
易操作的jQuery表单提示插件
Dec 01 Javascript
基于jquery实现表格无刷新分页
Jan 07 Javascript
30分钟快速掌握Bootstrap框架
May 24 Javascript
用react-redux实现react组件之间数据共享的方法
Jun 08 Javascript
使用vue-router beforEach实现判断用户登录跳转路由筛选功能
Jun 25 Javascript
vue中img src 动态加载本地json的图片路径写法
Apr 25 Javascript
利用Angular7开发一个Radio组件的全过程
Jul 11 Javascript
解决antd datepicker 获取时间默认少8个小时的问题
Oct 29 Javascript
记录一次websocket封装的过程
Nov 23 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和ACCESS写聊天室(五)
2006/10/09 PHP
php下检测字符串是否是utf8编码的代码
2008/06/28 PHP
PHP二维数组去重算法
2016/12/17 PHP
php读取本地json文件的实例
2018/03/07 PHP
PHP parse_ini_file函数的应用与扩展操作示例
2019/01/07 PHP
JavaScript 事件冒泡简介及应用
2010/01/11 Javascript
Raphael一个用于在网页中绘制矢量图形的Javascript库
2013/01/08 Javascript
JavaScript中的Number数字类型学习笔记
2016/05/26 Javascript
Bootstrap被封装的弹层
2016/07/20 Javascript
jQuery简单注册和禁用全局事件的方法
2016/07/25 Javascript
JavaScript学习笔记整理_setTimeout的应用
2016/09/19 Javascript
jQuery插件ajaxFileUpload使用实例解析
2016/10/19 Javascript
详解vue-cli + webpack 多页面实例应用
2017/04/25 Javascript
提升页面加载速度的插件InstantClick
2017/09/12 Javascript
layui表单验证select下拉框实现验证的方法
2019/09/05 Javascript
js中console在一行内打印字符串和对象的方法
2019/09/10 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
2020/10/31 Javascript
基于Vue+Webpack拆分路由文件实现管理
2020/11/16 Javascript
[02:53]DOTA2英雄昆卡基础教程
2013/11/25 DOTA
python实现自动登录人人网并采集信息的方法
2015/06/28 Python
python实现的系统实用log类实例
2015/06/30 Python
Python2.x与Python3.x的区别
2016/01/14 Python
Python实现优先级队列结构的方法详解
2016/06/02 Python
python 连接sqlite及简单操作
2017/06/30 Python
Python设计模式之命令模式原理与用法实例分析
2019/01/11 Python
详解用Python实现自动化监控远程服务器
2019/05/18 Python
Python ConfigParser模块的使用示例
2020/10/12 Python
python3 kubernetes api的使用示例
2021/01/12 Python
python实现经典排序算法的示例代码
2021/02/07 Python
DHC中国官方购物网站:日本通信销售No.1化妆品
2016/08/20 全球购物
美国首屈一指的高品质珠宝设计师和零售商:Allurez
2018/01/23 全球购物
读书活动总结
2014/04/28 职场文书
责任书范本
2014/08/25 职场文书
大学生个人年度总结范文
2015/02/15 职场文书
Python列表删除重复元素与图像相似度判断及删除实例代码
2021/05/07 Python
Golang jwt身份认证
2022/04/20 Golang