浏览器如何执行javascript&渲染异步 [英] how browser execute javascript & render asynchronous

查看:105
本文介绍了浏览器如何执行javascript&渲染异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是jsfiddle上的代码



 < script> function updateSync1(){for(var i = 0; i <1000; i ++){document.getElementById('output')。innerHTML = i; }} function updateSync2(){for(var i = 0; i <1000; i ++){setTimeout(document.getElementById('output')。innerHTML = i,0); }} function updateAsync(){var i = 0; function updateLater(){document.getElementById('output')。innerHTML =(i ++); if(i <1000){setTimeout(updateLater,0); }} updateLater(); }< / script>< div class =row btn_area> < button class =btn btn-infoonclick =updateSync1()>运行同步1< / button> < button class =btn btn-infoonclick =updateSync2()>运行同步2< / button> < button class =btn btn-infoonclick =updateAsync()>运行Async< / button> < span class =label label-info pull-rightstyle =display:block; id =output>< / span>< / div>  



http://jsfiddle.net/himaneasy/y1534ths/



当我点击运行同步1时,代码将直接运行到999.



当我点击运行同步2代码将直接运行到999.



当我点击运行异步时,页面将一个接一个。



任何人都可以帮忙解释Run Sync1和运行Sync2?
为什么运行同步2中的setTimeout不会逐个渲染?
谢谢!

解决方案

Javascript执行是单线程。它使用任务队列和堆栈来执行东西。



这段代码:

对于(var i = 0; i< length; i ++){
setTimeout(drawChartFunc,0);
}

将添加1000 setTimeouts 调用任务队列并随后排除所有这些(0 ms超时)。只有最后一个操作才会更新屏幕,因为所有的超时任务首先在堆栈中(循环后,任务队列包含1000个 setTimeout 调用)。每个超时执行 drawChartFunc 。现在, drawChartFunc 在任务队列中放置一个屏幕更新功能,但剩下的超时时间先到,所以首先执行下一个超时 - 屏幕更新功能只能执行 after 1000 setTimeout 调用完成(取自任务队列/堆栈)。这也是随后做的,但非常快。如果你的眼睛受到训练,看到纳秒转换,你可能会发现输出中的后续数字;)



现在



函数updateLater(){
drawChartFunc();

  
i ++;
if(i< length){
setTimeout(updateLater,0);
}
}

将首先运行 drawChartFunc 将屏幕更新放在任务队列上,然后在任务队列上增加 i ,然后添加新的$ $ $ $ c> setTimeout 到任务队列。换句话说,将 drawChartFunc 放在堆栈上,将屏幕更新放在堆栈上,两者都被执行,随后超时被放置在堆栈上,将 drawChartFunc 放在堆栈...等。



关于javascript任务队列/堆栈: 此视频 对我来说非常有用。



这是您的 jsFiddle ,重写了一下。它显示了两种方法的排队流程。


Here is the code on jsfiddle

<script>
  function updateSync1() {
    for (var i = 0; i < 1000; i++) {
      document.getElementById('output').innerHTML = i;
    }
  }

  function updateSync2() {
    for (var i = 0; i < 1000; i++) {
      setTimeout(document.getElementById('output').innerHTML = i, 0);
    }
  }

  function updateAsync() {
    var i = 0;

    function updateLater() {
      document.getElementById('output').innerHTML = (i++);
      if (i < 1000) {
        setTimeout(updateLater, 0);
      }
    }

    updateLater();
  }
</script>

<div class="row btn_area">
  <button class="btn btn-info" onclick="updateSync1()">Run Sync 1</button>
  <button class="btn btn-info" onclick="updateSync2()">Run Sync 2</button>
  <button class="btn btn-info" onclick="updateAsync()">Run Async</button>
  <span class="label label-info pull-right" style="display:block;" id="output"></span>
</div>

http://jsfiddle.net/himaneasy/y1534ths/

when I click 'Run Sync 1' the code will run to 999 directly.

When I click 'Run Sync 2',the code will run to 999 directly.

When I click 'Run Async',the page will render one by one.

Can anyone help explain the difference between Run Sync1 & Run Sync2? Why setTimeout in Run Sync 2 does not make it render one by one? Thanks!

解决方案

Javascript execution is single-threaded. It uses a task queue and the stack to execute stuff.

This piece of code:

for (var i=0;i<length;i++) {
     setTimeout(drawChartFunc,0);
}

Will add 1000 setTimeouts calls on the task queue and excute all of them subsequently (0 ms timeout). Only the last operation will update the the screen, because all of the timeout tasks come first on the stack (after the loop, the task queue contains 1000 setTimeout calls). Every timeout executes drawChartFunc. Now drawChartFunc does put a screen update function on the task queue, but the remaining timeouts come first, so first the next timeout is executed - the screen update functions can only be executed after the 1000 setTimeout calls are finished (taken of the task queue/stack). This is also done subsequently, but very fast. If your eyes where trained to see nanosecond transitions, you may have spotted the subsequent numbers in the output ;)

Now

function updateLater() {
     drawChartFunc();
     i++;
     if (i < length) { 
         setTimeout(updateLater, 0);
     }
 }

Will first run drawChartFunc putting the screen update on the task queue, then put increment i on the task queue and - if applicable - after that add a new setTimeout to the task queue. In other words, drawChartFunc is put on the stack, that puts the screen update on the stack, both are executed, an subsequently the timeout is put on the stack, putting drawChartFunc on the stack ... etc.

Concering the javascript task queue/stack: this video was really useful to me.

Here's your jsFiddle, rewritten a bit. It shows you the queuing process for both methods.

这篇关于浏览器如何执行javascript&amp;渲染异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆