javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout(0)的使用场景
在今天之前我一直以为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)的使用场景相关推荐
- 熊猫烧香真的那么厉害吗?我看是你们的安全意识太差了吧!
熊猫烧香真的那么厉害吗?我看是你们的安全意识太差了吧! 前几天一个朋友的电脑感染了病毒让我帮忙查杀,我大概看了一下,这个朋友的电脑admin没有密码,所有盘默认共享,因为我不是一个研究安全的专业人士, ...
- 跟vczh看实例学编译原理——一:Tinymoe的设计哲学
自从<序>胡扯了快一个月之后,终于迎来了正片.之所以系列文章叫<看实例学编译原理>,是因为整个系列会通过带大家一步一步实现Tinymoe的过程,来介绍编译原理的一些知识点. 但 ...
- 跟vczh看实例学编译原理——三:Tinymoe与无歧义语法分析
文章中引用的代码均来自https://github.com/vczh/tinymoe. 看了前面的三篇文章,大家应该基本对Tinymoe的代码有一个初步的感觉了.在正确分析"print su ...
- 我看暴库漏洞原理及规律
我看暴库漏洞原理及规律 SQL注入流行很久了,我们找漏洞注入目的无非是想得到数据库内的东西,比如用户名密码等,更进一步的MSSQL数据库还可以借此获得权限.基于Access的基础来说,如果我们不用注入 ...
- js基础之setTimeout与setInterval原理分析
setTimeout与setInterval概述 setTimeout与setInterval是JavaScript引擎提供的两个定时器方法,分别用于函数的延时执行和循环调用.前者的主要思想是通过一个 ...
- 量子计算机科学原理,1000字看懂IBM量子计算机原理
原标题:1000字看懂IBM量子计算机原理 IBM建造了一台真正的量子计算机,开启了量子计算的新纪元.为了得瑟一下,近日他们启动了量子计算云服务,让外部程序员和研究者可以通过算法来测试他们的量子芯片, ...
- 跟vczh看实例学编译原理——零:序言
在<如何设计一门语言>里面,我讲了一些语言方面的东西,还有痛快的喷了一些XX粉什么的.不过单纯讲这个也是很无聊的,所以我开了这个<跟vczh看实例学编译原理>系列,意在科普一些 ...
- 探究.NET的bin引用程序集运行机制看.NET程序集部署原理
探究.NET的bin引用程序集运行机制 看.NET程序集部署原理 新建一个最简单的网站,并引用使用程序集Nhibernate.dll,页面代码为 运行后输出的结果 .NET 程序集部署程序 ...
- 动画图解一般看不见的机械原理
动画图解一般看不见的机械原理 动画图解一般看不见的机械原理--更新多款发动机,手枪--现代生活离不开各种机械,无数复杂的机械走进了我们寻常百姓的生活中,小到我们家里客厅墙上的挂钟,大到出门上班用以代步 ...
最新文章
- java gps 距离计算_java计算两个GPS经纬度之间的距离(转)
- 计算机课程大作业答案,计算机接口技术课堂大作业(1)参考答案
- css入门教程 网页首字下沉,CSS制作首字下沉_CSS Inline Layout Module, initial-letter, CSS3 教程_w3cplus...
- SpringBoot+Vue使用Get请求时提示:Error parsing HTTP request header
- 电脑桌面便签小工具_iPhone12系列售价曝光,苹果手机上有什么好用的便签记事本软件推荐吗...
- Python学习_字符串格式化
- php百度坐标转腾讯坐标,PHP腾讯与百度坐标转换
- cmake 配置生成后事件_cmake 管理debug release
- 安卓 开源 挣钱_在开源中赚钱并享受乐趣
- 矢量算法java,矢量线的一种栅格化算法
- windows2008 服务器时间格式改不过来_我用VNPY 1天时间搭建自主量化交易(程序化交易)平台...
- Linux修改终端提示符
- 从入门到入土:Nessus出击:使用nessus扫描某台靶机
- php常用技术与thinkphp5,thinkPHP5框架路由常用知识点汇总
- Python二维数组,坑苦了
- 浏览器播放RTSP视频流几种解决方案
- Java实现 LeetCode 824 山羊拉丁文(暴力)
- Kotlin: Classifier ‘Demo1‘ does not have a companion object, and thus must be initialized here
- 软件破解简单示例演示
- 如何使用COM-Hunter检测持久化COM劫持漏洞