javascript代码实例教程-Javascript定时器(一)――单线程

发布时间:2019-01-24 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-Javascript定时器(一)――单线程脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。 一、JavaScript 引擎是单线程的

 

可以从下面的代码中看到,第一个用setTimeout中的代码是死循环,由于是单线程,下面的两个定时器就没机会执行了。

 

<script tyPE="text/javascript">

    setTimeout( function(){ while(true){} } , 100); 

    setTimeout( function(){ alert(&#39;你好!setTimeout'); } , 200); 

    setInterval( function(){ alert('你好!setInterval'); }  , 200); 

</script>

浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现3个常驻线程:javascript引擎线程,GUI渲染线程,浏览器事件触发线程。

 

JavaScript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来然后加以处理,浏览器无论再什么时候都只有一个JS线程在运行JS程序。

GUI渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。

浏览器事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

 

 

  由上图可看出,浏览器中的JavaScript引擎是基于事件驱动的,这里的事件可看作是浏览器派给它的各种任务,JavaScript引擎一直等待着任务队列中任务的到来,由于单线程关系,这些任务得进行排队,一个接着一个被引擎处理。

 

t1、t2....tn表示不同的时间点,tn下面对应的小方块代表该时间点的任务。

 

t1时刻:

 

GUI渲染线程

浏览器事件触发线程:

在t1时间段内,首先是用户点击了一个鼠标键,点击被浏览器事件触发线程捕捉后形成一个鼠标点击事件,由图可知,对于JavaScript引擎线程来说,这事件是由其它线程异步传到任务队列尾的,由于引擎正在处理t1时的任务,这个鼠标点击事件正在等待处理。

定时触发线程:

这里的浏览器模型定时计数器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的,如果处于阻塞线程状态就计不了时,它必须依赖外部来计时并触发定时,所以队列中的定时事件是异步事件。

在这t1的时间段内,继鼠标点击事件触发后,先前已设置的setTimeout定时也到达了,此刻对JavaScript引擎来说,定时触发线程产生了一个异步定时事件并放到任务队列中,该事件被排到点击事件回调之后,等待处理。同理,还是在t1时间段内,接下来某个setInterval定时器也被添加了,由于是间隔定时,在t1段内连续被触发了两次,这两个事件被排到队尾等待处理。

ajax异步请求:

浏览器新开一个http线程请求,当请求的状态变更时,如果先前已设置回调,这异步线程就产生状态变更事件放到JavaScript引擎的处理队列中等待处理。

二、任务的执行顺序不同,显示结果也不同

 

1)未使用setTimeout函数

 

在网上找到的一段代码实例,这里用来演示一下。

 

复制代码

<a href="#" id="doBTn">do something</a>

<p id="status"></p>

<script type="text/javascript">

      VAR doBtn = document.getElementById('doBtn')

          , status = document.getElementById('status');

 

      function sleep(ms) {

        var start = new Date();

        while (new Date() - start <= ms) {}

      }

      

      doBtn.onclick = function(e) {

          status.innerHTML = 'doing...please waIT...';  

          sleep(3000);  // 模拟一个耗时较长的计算过程,3s

          status.innerHTML = 'done';  

          return false;

      };

</script>

复制代码

我在firefox中执行了上面的代码。计划是点击“do something”按钮,然后显示“doing...please wait...”,接着执行sleep,最后显示“done”。

 

但是结果是点击后,浏览器卡住3秒左右,最后直接显示done。

 

分析下看出,在做status.innerHTML设置的时候,是需要执行GUI渲染线程的,但是现在还在执行JavaScript引擎线程,而JavaScript引擎线程与GUI渲染线程是互斥的,所以就最后显示了done。

 

 

 

2)使用了setTimeout函数

 

复制代码

<a href="#" id="doBtn2">do something timer</a>

<p id="status2"></p>

<script type="text/javascript">

      var doBtn2 = document.getElementById('doBtn2')

          , status2 = document.getElementById('status2');

 

      function sleep2(ms) {

        var start = new Date();

        while (new Date() - start <= ms) {}

      }

      

      doBtn2.onclick = function(e) {

          status2.innerHTML = 'doing...please wait...'; 

          setTimeout(function() {

            sleep2(3000); 

            status2.innerHTML = 'done'; 

          }, 100); 

          return false;

      };

</script>

复制代码

在“doing...please wait...”后面加了个setTimeout,延时执行,给了浏览器渲染的时间,这个时候会显示出“doing...please wait...”的字样,然后执行sleep函数,最后显示“done”。

 

 

 

后面有网友发现在firefox中不起作用,的确有这个问题,后面我修改了一下代码,将局部变量的声明,onclick的绑定放到了window.onload事件中,等页面结构加载完成后,我再做脚本操作。

 

复制代码

<script type="text/javascript">

      function sleep(ms) {

        //...

      }

      window.onload = function() {

            var doBtn = document.getElementById('doBtn'),

            status = document.getElementById('status');

            

            var doBtn2 = document.getElementById('doBtn2')

              , status2 = document.getElementById('status2');

              

            doBtn.onclick = function(e) {

                //...

            };

            doBtn2.onclick = function(e) {

                //...

            };

      };

</script>

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-Javascript定时器(一)――单线程全部内容,希望文章能够帮你解决javascript代码实例教程-Javascript定时器(一)――单线程所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。