在今天之前我一直以为setTimeout这个函数是异步的,无意中看到了一篇关于setTimeout的文章。发现自己曾经的认识全是错误的,赶紧总结下。

先看一段代码:

var start = new Date();
setTimeout(function(){var end = new Date();console.log("Time elapsed: ", end - start, "ms");
}, 500);while (new Date - start <= 1000)
{}

运行这段脚本能够看到:Time elapsed的值大概在1001ms左右,肯定会超过1000ms。也就是说:setTimeout失效了,指定的函数并没有在500ms后运行。而是延迟到1000ms后才运行。

再看一段代码:

function a()
{setTimeout(function(){console.log(1);},0);console.log(2);
}
a();

执行这段脚本能够看到:先打印2后打印1,我们在setTimeout里面指定了0ms,希望能马上执行,可是实际上没有效果。

想要理解上面的2段代码,我们得了解一下javascript中setTimeout的实现原理。首先牢记一点:JavaScript 是单线程运行的,也就是无法同一时候运行多段代码。

以下这段解释来自这篇博客:

        JavaScript是单线程运行的,无法同一时候运行多段代码。当某一段代码正在运行的时候,全部兴许的任务都必须等待,形成一个队列。

一旦当前任务运行完毕,再从队列中取出下一个任务,这也常被称为 “堵塞式运行”。所以一次鼠标点击,或是计时器到达时间点,或是Ajax请求完毕触发了回调函数。这些事件处理程序或回调函数都不会马上运行,而是马上排队。一旦线程有空暇就运行。假如当前 JavaScript线程正在运行一段非常耗时的代码,此时发生了一次鼠标点击。那么事件处理程序就被堵塞。用户也无法马上看到反馈。事件处理程序会被放入任务队列。直到前面的代码结束以后才会開始运行。假设代码中设定了一个 setTimeout,那么浏览器便会在合适的时间。将代码插入任务队列。假设这个时间设为 0,就代表马上插入队列,但不是马上运行。仍然要等待前面代码运行完成。

所以 setTimeout 并不能保证运行的时间。是否及时运行取决于 JavaScript 线程是拥挤还是空暇。


也就是说setTimeout仅仅能保证在指定的时间过后将任务(须要运行的函数)插入队列等候,并不保证这个任务在什么时候运行。运行javascript的线程会在空暇的时候,自行从队列中取出任务然后运行它。javascript通过这样的队列机制。给我们制造一个异步运行的假象。

var start = new Date();
setTimeout(function(){var end = new Date();console.log("Time elapsed: ", end - start, "ms");
}, 500);console.log("task finished.");

我们之所以会感觉到这段代码是在异步运行,这是由于javascript线程并没有由于什么耗时操作而堵塞,所以能够非常快地取出排队队列中的任务然后运行它。

如今我们知道了setTimeout的原理了,如今看下setTimeout(0)的使用场景。以下这个样例来自这篇文章。

<input type="text" οnkeydοwn="show(this.value)">
<div></div>
<script type="text/javascript">function show(val) {document.getElementsByTagName('div')[0].innerHTML = val;}
</script>

这里绑定了 keydown 事件,意图是当用户在文本框里输入字符时。将输入的内容实时地在 <div> 中显示出来。可是实际效果并不是如此,能够发现。每按下一个字符时,<div> 中仅仅能显示出之前的内容,无法得到当前的字符。

<input type="text" οnkeydοwn="var self=this; setTimeout(function() {show(self.value)}, 0)">
<div></div>
<script type="text/javascript">function show(val) {document.getElementsByTagName('div')[0].innerHTML = val;}
</script>

这段代码使用了setTimeout(0)就能够实现需要的效果了。

这里事实上涉及2个任务,1个是将键盘输入的字符回写到输入框中。一个是获取文本框的值将其写入div中。第一个是浏览器自身的默认行为。一个是我们自己编写的代码。非常显然。必需要先让浏览器将字符回写到文本框。然后我们才干获取其内容写到div中。改变顺序,这这正是setTimeout(0)的作用。

參考文章:setTimeout(0) 的作用

javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout(0)的使用场景相关推荐

  1. 熊猫烧香真的那么厉害吗?我看是你们的安全意识太差了吧!

    熊猫烧香真的那么厉害吗?我看是你们的安全意识太差了吧! 前几天一个朋友的电脑感染了病毒让我帮忙查杀,我大概看了一下,这个朋友的电脑admin没有密码,所有盘默认共享,因为我不是一个研究安全的专业人士, ...

  2. 跟vczh看实例学编译原理——一:Tinymoe的设计哲学

    自从<序>胡扯了快一个月之后,终于迎来了正片.之所以系列文章叫<看实例学编译原理>,是因为整个系列会通过带大家一步一步实现Tinymoe的过程,来介绍编译原理的一些知识点. 但 ...

  3. 跟vczh看实例学编译原理——三:Tinymoe与无歧义语法分析

    文章中引用的代码均来自https://github.com/vczh/tinymoe. 看了前面的三篇文章,大家应该基本对Tinymoe的代码有一个初步的感觉了.在正确分析"print su ...

  4. 我看暴库漏洞原理及规律

    我看暴库漏洞原理及规律 SQL注入流行很久了,我们找漏洞注入目的无非是想得到数据库内的东西,比如用户名密码等,更进一步的MSSQL数据库还可以借此获得权限.基于Access的基础来说,如果我们不用注入 ...

  5. js基础之setTimeout与setInterval原理分析

    setTimeout与setInterval概述 setTimeout与setInterval是JavaScript引擎提供的两个定时器方法,分别用于函数的延时执行和循环调用.前者的主要思想是通过一个 ...

  6. 量子计算机科学原理,1000字看懂IBM量子计算机原理

    原标题:1000字看懂IBM量子计算机原理 IBM建造了一台真正的量子计算机,开启了量子计算的新纪元.为了得瑟一下,近日他们启动了量子计算云服务,让外部程序员和研究者可以通过算法来测试他们的量子芯片, ...

  7. 跟vczh看实例学编译原理——零:序言

    在<如何设计一门语言>里面,我讲了一些语言方面的东西,还有痛快的喷了一些XX粉什么的.不过单纯讲这个也是很无聊的,所以我开了这个<跟vczh看实例学编译原理>系列,意在科普一些 ...

  8. 探究.NET的bin引用程序集运行机制看.NET程序集部署原理

    探究.NET的bin引用程序集运行机制 看.NET程序集部署原理 新建一个最简单的网站,并引用使用程序集Nhibernate.dll,页面代码为       运行后输出的结果 .NET 程序集部署程序 ...

  9. 动画图解一般看不见的机械原理

    动画图解一般看不见的机械原理 动画图解一般看不见的机械原理--更新多款发动机,手枪--现代生活离不开各种机械,无数复杂的机械走进了我们寻常百姓的生活中,小到我们家里客厅墙上的挂钟,大到出门上班用以代步 ...

最新文章

  1. java gps 距离计算_java计算两个GPS经纬度之间的距离(转)
  2. 计算机课程大作业答案,计算机接口技术课堂大作业(1)参考答案
  3. css入门教程 网页首字下沉,CSS制作首字下沉_CSS Inline Layout Module, initial-letter, CSS3 教程_w3cplus...
  4. SpringBoot+Vue使用Get请求时提示:Error parsing HTTP request header
  5. 电脑桌面便签小工具_iPhone12系列售价曝光,苹果手机上有什么好用的便签记事本软件推荐吗...
  6. Python学习_字符串格式化
  7. php百度坐标转腾讯坐标,PHP腾讯与百度坐标转换
  8. cmake 配置生成后事件_cmake 管理debug release
  9. 安卓 开源 挣钱_在开源中赚钱并享受乐趣
  10. 矢量算法java,矢量线的一种栅格化算法
  11. windows2008 服务器时间格式改不过来_我用VNPY 1天时间搭建自主量化交易(程序化交易)平台...
  12. Linux修改终端提示符
  13. 从入门到入土:Nessus出击:使用nessus扫描某台靶机
  14. php常用技术与thinkphp5,thinkPHP5框架路由常用知识点汇总
  15. Python二维数组,坑苦了
  16. 浏览器播放RTSP视频流几种解决方案
  17. Java实现 LeetCode 824 山羊拉丁文(暴力)
  18. Kotlin: Classifier ‘Demo1‘ does not have a companion object, and thus must be initialized here
  19. 软件破解简单示例演示
  20. 如何使用COM-Hunter检测持久化COM劫持漏洞

热门文章

  1. Eureka源码分析
  2. Python环境搭建及第三方库安装和卸载
  3. github图---小章鱼图标
  4. CometOJ#6 双倍快乐(简单DP)
  5. Windows 聚焦的锁屏壁纸设置为桌面壁纸
  6. 关于Keychain
  7. centos系统设置局域网静态IP
  8. 验证Oracle收集统计信息参数granularity数据分析的力度
  9. 配置云服务器 FTP 服务
  10. 小兔伴伴家庭动物园AR智能早教产品上市