setTimeout的实现原理以及setTimeout(0)的使用场景
先看一段代码:
- 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" onkeydown="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" onkeydown="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)的作用。
原文链接:http://blog.csdn.net/aitangyong/article/details/46800615
尽管setTimeout的delay是0,也会作为一次异步调用,而每次异步调用结束后都会render页面
setTimeout的实现原理以及setTimeout(0)的使用场景的更多相关文章
- javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout(0)的使用场景
在今天之前我一直以为setTimeout这个函数是异步的,无意中看到了一篇关于setTimeout的文章.发现自己曾经的认识全是错误的,赶紧总结下. 先看一段代码: var start = new D ...
- setTimeout,setInterval原理
function a() { setTimeout(function(){alert(1)},0); alert(2); } a(); 和其他的编程语言一样,Javascript中的函数调用也是通过堆 ...
- setTimeout的核心原理和巧用
你所不了解的setTimeout 发表于 2015年11月23日 by 愚人码头 被浏览 14,756 次 分享到: 0 小编推荐:掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue ...
- Apache kafka原理与特性(0.8V)
前言: kafka是一个轻量级的/分布式的/具备replication能力的日志采集组件,通常被集成到应用系统中,收集"用户行为日志"等,并可以使用各种消费终端(consumer) ...
- 【转载】Apache kafka原理与特性(0.8V)
http://blog.csdn.net/xiaolang85/article/details/37821209 前言: kafka是一个轻量级的/分布式的/具备replication能力的日志采集组 ...
- 结合 category 工作原理分析 OC2.0 中的 runtime
绝大多数 iOS 开发者在学习 runtime 时都阅读过 runtime.h 文件中的这段代码: struct objc_class { Class isa OBJC_ISA_AVAILABILI ...
- Spark的RDD原理以及2.0特性的介绍
转载自:http://www.tuicool.com/articles/7VNfyif 王联辉,曾在腾讯,Intel 等公司从事大数据相关的工作.2013 年 - 2016 年先后负责腾讯 Yarn ...
- JAVA的JVM虚拟机工作原理.V.1.0.0
注意:一下内容纯属个人理解,如有错误,欢迎批评指正. (90度弯腰)谢谢. java在JVM上的运行过程: 1,编辑好的java代码(IDE无报错,测试运行无错误): 2,java源代码通过javac ...
- kafka系列九、kafka事务原理、事务API和使用场景
一.事务场景 最简单的需求是producer发的多条消息组成一个事务这些消息需要对consumer同时可见或者同时不可见 . producer可能会给多个topic,多个partition发消息,这些 ...
随机推荐
- Qt 学习之路 2(29):绘制设备
Qt 学习之路 2(29):绘制设备 豆子 2012年12月3日 Qt 学习之路 2 28条评论 绘图设备是继承QPainterDevice的类.QPaintDevice就是能够进行绘制的类,也就是说 ...
- svn学习笔记(一)
一.svn介绍 1.1 项目管理中的版本控制问题 通常软件开发由多人协作开发,如果对代码文件.配置文件.文档等没有进行版本控制,将会出现很多问题: 备份多个版本,占用磁盘空间大 解决代码冲突困难 容易 ...
- C++_类入门2-使用类
进一步探讨类的特征,重点是类设计技术,而不是通用原理.一些特性很容易,一些特性很微妙. 运算符重载 目的是使C++操作更美观,更接近于内置类型的操作. 隐藏了内部的实现机理,并强调了实质. 格式:op ...
- 有用的 Angular CLI 命令参数
这是一些有用的 Angular 5 CLI 命令参数,注意参数前面的-和--的不同... 1. 指定build的输出为production version,合并优化css and js files. ...
- 从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js
从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js /************************************************************* ...
- Linux按键设备驱动一
① request_irq函数用于注册中断 int request_irq(unsigned int irq, void(*handler)(int, void*, struct pt_reg*), ...
- PIE SDK线元素的绘制
1. 功能简介 在数据的处理中会用到线元素的绘制,目前PIE SDK支持ILineSymbol的线元素的绘制,LineSymbol对象是用于修饰线状对象的符号,它包括CartographicLineS ...
- 用 fmt格式化候时间
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <div ...
- jdk监控tomcat
一, tomcat配置文件 在tomcat的配置文件中添加被监控的项 #在tomcat配置文件中开启监控功能 vim /application/tomcat/bin/catalina.sh +97 C ...
- (转)企业Shell实战-MySQL分库分表备份脚本
本文来自http://www.xuliangwei.com/xubusi/252.html 免费视频讲解见 http://edu.51cto.com/course/course_id-5064.htm ...