浏览器如何执行javascript和渲染异步

jas*_*ong 4 javascript performance dom settimeout dom-events

这是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>
Run Code Online (Sandbox Code Playgroud)

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

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

当我单击"运行同步2"时,代码将直接运行到999.

当我单击"运行异步"时,页面将逐个呈现.

任何人都可以帮助解释Run Sync1和Run Sync2之间的区别吗?为什么运行同步2中的setTimeout不能逐个渲染?谢谢!

Koo*_*Inc 7

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

这段代码:

for (var i=0;i<length;i++) {
     setTimeout(drawChartFunc,0);
}
Run Code Online (Sandbox Code Playgroud)

setTimeouts在任务队列上添加1000个调用并随后执行所有调用(0毫秒超时).只有最后一个操作才会更新屏幕,因为所有超时任务都首先出现在堆栈上(循环之后,任务队列包含1000个setTimeout调用).每个超时执行drawChartFunc.现在drawChartFunc确实在任务队列上放置了一个屏幕更新功能,但剩下的超时时间先到,所以首先执行下一个超时 - 屏幕更新功能只能在1000次调用完成执行setTimeout(取自任务队列/堆栈) .这也是随后完成的,但速度非常快.如果您的眼睛经过训练可以看到纳秒转换,您可能已经发现了输出中的后续数字;)

现在

function updateLater() {
     drawChartFunc();
     i++;
     if (i < length) { 
         setTimeout(updateLater, 0);
     }
 }
Run Code Online (Sandbox Code Playgroud)

首先drawChartFunc将屏幕更新放在任务队列上,然后将增量i放在任务队列上 - 如果适用 - 之后将新setTimeout增加到任务队列.换句话说,drawChartFunc放在堆栈上,将屏幕更新放在堆栈上,两者都被执行,随后超时被放在堆栈上,放在drawChartFunc堆栈上......等等.

确认javascript任务队列/堆栈:这个视频对我来说非常有用.

这是你的jsFiddle,重写了一下.它显示了两种方法的排队过程.