zoukankan      html  css  js  c++  java
  • setTimeout的实现原理以及setTimeout(0)的使用场景

     

    先看一段代码:

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

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

    再看一段代码:

    [javascript] view plain copy
     
    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通过这种队列机制,给我们制造一个异步执行的假象。

    [javascript] view plain copy
     
    1. var start = new Date();  
    2. setTimeout(function(){  
    3.     var end = new Date();  
    4.     console.log("Time elapsed: ", end - start, "ms");  
    5. }, 500);  
    6.   
    7. console.log("task finished.");  
    我们之所以会感觉到这段代码是在异步执行,这是因为javascript线程并没有因为什么耗时操作而阻塞,所以可以很快地取出排队队列中的任务然后执行它。

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

    [html] view plain copy
     
    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> 中只能显示出之前的内容,无法得到当前的字符。
    [html] view plain copy
     
    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页面

    --------------------------------------

    另外在项目中,有根据事件改编dom的高度,父级dom和子元素的高度同时改变

    setTimeout(() => {
                        that.xl.changeIframeSize({  null, height: 'calc(100% - ' + that.iframeBottom + 'px)' });
                        document.getElementById('containter').style.height='100%';
                    }, 0);
    如果不加setTimeout(0) 会出现元素闪动问题
  • 相关阅读:
    ASP.NET 表单验证 Part.1(理解表单验证)
    Silverlight 简介 Part.3(设计 Siverlight 页面)
    ASP.NET 成员资格 Part.3(LoginStatus、LoginView、PasswordRecovery)
    ASP.NET 网站部署 Part.1(安装IIS、复制文件部署网站)
    ASP.NET Dynamic Data Part.1(创建动态数据应用程序)
    ASP.NET 安全模型 Part.2(SSL)
    ASP.NET MVC Part.2(扩展基本的 MVC 应用程序)
    ASP.NET 网站部署 Part.2(使用 Web 部署)
    开发高级 Web 部件
    创建 Web 部件(WebPart 类、简单的 Web 部件)
  • 原文地址:https://www.cnblogs.com/fangsmile/p/6387221.html
Copyright © 2011-2022 走看看