先看一段代码:

  1. var start = new Date();
  2. setTimeout(function(){
  3. var end = new Date();
  4. console.log("Time elapsed: ", end - start, "ms");
  5. }, 500);
  6. while (new Date - start <= 1000)
  7. {
  8. }

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

再看一段代码:

  1. function a()
  2. {
  3. setTimeout(function(){console.log(1);},0);
  4. console.log(2);
  5. }
  6. a();

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

想要理解上面的2段代码,我们得了解一下JavaScript中setTimeout的实现原理。首先牢记一点:JavaScript 是单线程执行的,也就是无法同时执行多段代码。下面这段解释来自这篇博客

        JavaScript是单线程执行的,无法同时执行多段代码。当某一段代码正在执行的时候,所有后续的任务都必须等待,形成一个队列。一旦当前任务执行完毕,再从队列中取出下一个任务,这也常被称为 “阻塞式执行”。所以一次鼠标点击,或是计时器到达时间点,或是Ajax请求完成触发了回调函数,这些事件处理程序或回调函数都不会立即运行,而是立即排队,一旦线程有空闲就执行。假如当前 JavaScript线程正在执行一段很耗时的代码,此时发生了一次鼠标点击,那么事件处理程序就被阻塞,用户也无法立即看到反馈,事件处理程序会被放入任务队列,直到前面的代码结束以后才会开始执行。如果代码中设定了一个 setTimeout,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为 0,就代表立即插入队列,但不是立即执行,仍然要等待前面代码执行完毕。所以 setTimeout 并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲。

 

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

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

我们之所以会感觉到这段代码是在异步执行,这是因为javascript线程并没有因为什么耗时操作而阻塞,所以可以很快地取出排队队列中的任务然后执行它。

现在我们知道了setTimeout的原理了,现在看下setTimeout(0)的使用场景。下面这个例子来自这篇文章

  1. <input type="text" onkeydown="show(this.value)">
  2. <div></div>
  3. <script type="text/javascript">
  4. function show(val) {
  5. document.getElementsByTagName('div')[0].innerHTML = val;
  6. }
  7. </script>

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

  1. <input type="text" onkeydown="var self=this; setTimeout(function() {show(self.value)}, 0)">
  2. <div></div>
  3. <script type="text/javascript">
  4. function show(val) {
  5. document.getElementsByTagName('div')[0].innerHTML = val;
  6. }
  7. </script>

这段代码使用了setTimeout(0)就可以实现需要的效果了。这里其实涉及2个任务,1个是将键盘输入的字符回写到输入框中,一个是获取文本框的值将其写入div中。第一个是浏览器自身的默认行为,一个是我们自己编写的代码。很显然,必须要先让浏览器将字符回写到文本框,然后我们才能获取其内容写到div中,如果立即执行获取文本框的值,其实输入框还没有输入的内容。改变顺序,这这正是setTimeout(0)的作用。

原文链接:http://blog.csdn.net/aitangyong/article/details/46800615

尽管setTimeout的delay是0,也会作为一次异步调用,而每次异步调用结束后都会render页面

setTimeout的实现原理以及setTimeout(0)的使用场景的更多相关文章

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

    在今天之前我一直以为setTimeout这个函数是异步的,无意中看到了一篇关于setTimeout的文章.发现自己曾经的认识全是错误的,赶紧总结下. 先看一段代码: var start = new D ...

  2. setTimeout,setInterval原理

    function a() { setTimeout(function(){alert(1)},0); alert(2); } a(); 和其他的编程语言一样,Javascript中的函数调用也是通过堆 ...

  3. setTimeout的核心原理和巧用

    你所不了解的setTimeout 发表于 2015年11月23日 by 愚人码头 被浏览 14,756 次 分享到: 0 小编推荐:掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue ...

  4. Apache kafka原理与特性(0.8V)

    前言: kafka是一个轻量级的/分布式的/具备replication能力的日志采集组件,通常被集成到应用系统中,收集"用户行为日志"等,并可以使用各种消费终端(consumer) ...

  5. 【转载】Apache kafka原理与特性(0.8V)

    http://blog.csdn.net/xiaolang85/article/details/37821209 前言: kafka是一个轻量级的/分布式的/具备replication能力的日志采集组 ...

  6. 结合 category 工作原理分析 OC2.0 中的 runtime

    绝大多数 iOS 开发者在学习 runtime 时都阅读过 runtime.h 文件中的这段代码: struct objc_class { Class isa  OBJC_ISA_AVAILABILI ...

  7. Spark的RDD原理以及2.0特性的介绍

    转载自:http://www.tuicool.com/articles/7VNfyif 王联辉,曾在腾讯,Intel 等公司从事大数据相关的工作.2013 年 - 2016 年先后负责腾讯 Yarn ...

  8. JAVA的JVM虚拟机工作原理.V.1.0.0

    注意:一下内容纯属个人理解,如有错误,欢迎批评指正. (90度弯腰)谢谢. java在JVM上的运行过程: 1,编辑好的java代码(IDE无报错,测试运行无错误): 2,java源代码通过javac ...

  9. kafka系列九、kafka事务原理、事务API和使用场景

    一.事务场景 最简单的需求是producer发的多条消息组成一个事务这些消息需要对consumer同时可见或者同时不可见 . producer可能会给多个topic,多个partition发消息,这些 ...

随机推荐

  1. VSLAM技术框架详述

    最早的SLAM雏形是在军事(核潜艇的海底定位)上的应用,主要传感器是军用雷达.SLAM技术发展到如今已经几十年,目前以激光雷达作为主传感器的SLAM技术比较稳定.可靠,仍然是主流的技术方案.但随着最近 ...

  2. EasyUI学习笔记(一)EasyUI入门

    一.EasyUI下载 EasyUI官方下载地址:http://www.jeasyui.com/download/index.php,目前最新的版本是:jquery-easyui-1.7.2 解压后得到 ...

  3. ubuntu设置静态 ip

    查看ip和DNS 终端输入ifconfig获取ip,子网掩码.输入nm-tool获取网关,DNS 修改配置文件/etc/network/interfaces root@ubuntu:~# sudo g ...

  4. C++_友元1-友元类是什么

    友元函数:不是类的成员函数,但是能够访问类的私有数据成员. 之前有个矛盾就是规定非成员函数不能直接访问类的私有数据,但是这会儿却可以,但那只是针对常规非成员函数而言,特殊的非成员函数就可以访问类的私有 ...

  5. BT网站--Python开发爬虫代替.NET

    BT网站-奥修磁力-Python开发爬虫代替.NET写的爬虫,主要演示访问速度和在一千万左右的HASH记录中索引效率. IBMID 磁力下载- WWW.IBMID.COM  现在用的是Python + ...

  6. LightOJ - 1234 分块预处理

    求∑1/i,但是范围很大 和bitmap的想法一样,分个块,均摊复杂度就降下来了 //到底排行榜上的0ms是怎么做到的? #include<bits/stdc++.h> using nam ...

  7. Apache Shiro(二)-登录认证和权限管理数据库操作

    数据库支持 在上一篇中使用ini 配置文件进行了相关权限数据的配置. 但是实际工作中,我们都会把权限相关的内容放在数据库里. 所以本知识点讲解如何放在数据库里来撸. RBAC 概念 RBAC 是当下权 ...

  8. javaScript 和 node.js 的一些文章收集

    这里收集了一些文章的链接,方便自己查询翻看,也避免把别人的成果复制过来再发布,节约时间. ThinkJS 3 正式版发布 我来回答饿了么大前端的问题(1) 一起理解 Virtual DOM 探讨Nod ...

  9. Transform 引起的 z-index "失效"

    重新学习CSS后的第三天,学习制作阴影的过程中,发现的问题:设置了box-shadow后展现的阴影: 添加transform:rotate(10deg);后的效果: 查看CodePen例子:阴影效果 ...

  10. c语言3种方式实现参数传递

    学习计算机已经两年了,参数传递已经成功恶心了我两年,今天在写二叉树遍历的时候成功对此忍无可忍.本文是在阅读https://blog.csdn.net/u013097971/article/detail ...