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 表单验证常见正则
Sep 28 Javascript
基于jQuery的的一个隔行变色,鼠标移动变色的小插件
Jul 06 Javascript
js 优化次数过多的循环 考虑到性能问题
Mar 05 Javascript
js数组的操作详解
Mar 27 Javascript
js读取json的两种常用方法示例介绍
Oct 19 Javascript
深入学习js瀑布流布局
Oct 14 Javascript
详解JSON1:使用TSQL查询数据和更新JSON数据
Nov 21 Javascript
Vue学习笔记进阶篇之函数化组件解析
Jul 21 Javascript
基于BootStrap multiselect.js实现的下拉框联动效果
Jul 28 Javascript
jquery获取链接地址和跳转详解(推荐)
Aug 15 jQuery
AngularJS 将再发布一个重要版本 然后进入长期支持阶段
Jan 31 Javascript
vue修饰符.capture和.self的区别
Apr 22 Vue.js
如何获取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安全防范技巧分享
2011/11/03 PHP
用PHP提取中英文词语以及数字的首字母的方法介绍
2013/04/23 PHP
php异常处理捕获错误整理
2019/09/23 PHP
解决PHP curl或file_get_contents下载图片损坏或无法打开的问题
2019/10/11 PHP
在IE模态窗口中自由查看HTML源码的方法
2007/03/08 Javascript
Mootools 1.2教程 定时器和哈希简介
2009/09/15 Javascript
Jquery获取和修改img的src值的方法
2014/02/17 Javascript
jQuery聚合函数实例
2015/05/21 Javascript
JS实现灵巧的下拉导航效果代码
2015/08/25 Javascript
VueJS 集成 Medium Editor的示例代码 (自定义编辑器按钮)
2017/08/24 Javascript
微信小程序左滑动显示菜单功能的实现
2018/06/14 Javascript
vue使用el-upload上传文件及Feign服务间传递文件的方法
2019/03/15 Javascript
详解vue中使用vue-quill-editor富文本小结(图片上传)
2019/04/24 Javascript
用Vue编写抽象组件的方法
2019/05/06 Javascript
javascript使用链接跨域下载图片
2019/11/01 Javascript
vue实现配置全局访问路径头(axios)
2019/11/01 Javascript
vue 返回上一页,页面样式错乱的解决
2019/11/14 Javascript
解决Layui 表格自适应高度的问题
2019/11/15 Javascript
JavaScript setInterval()与setTimeout()计时器
2019/12/27 Javascript
vue项目中使用bpmn为节点添加颜色的方法
2020/04/30 Javascript
实例讲解Python设计模式编程之工厂方法模式的使用
2016/03/02 Python
Python正则表达式非贪婪、多行匹配功能示例
2017/08/08 Python
Django自定义过滤器定义与用法示例
2018/03/22 Python
Python装饰器原理与简单用法实例分析
2018/04/29 Python
python实现周期方波信号频谱图
2018/07/21 Python
python 获取url中的参数列表实例
2018/12/18 Python
Django中间件基础用法详解
2019/07/18 Python
VSCode中自动为Python文件添加头部注释
2019/11/14 Python
修改Pandas的行或列的名字(重命名)
2019/12/18 Python
canvas进阶之如何画出平滑的曲线
2018/10/15 HTML / CSS
加拿大时尚床上用品零售商:QE Home | Quilts Etc
2018/01/22 全球购物
荷兰美妆护肤品海淘网站:Beautinow(中文)
2020/11/22 全球购物
食品业务员岗位职责
2014/03/18 职场文书
搞笑婚前保证书
2015/02/28 职场文书
MySQL的InnoDB存储引擎的数据页结构详解
2022/03/03 MySQL
Python+Pillow+Pytesseract实现验证码识别
2022/05/11 Python