浏览器如何执行Javascript和异步呈现 [英] How browser executes Javascript and renders asynchronously

查看:82
本文介绍了浏览器如何执行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/

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

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

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

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.

谁能帮助解释Run Sync1和运行Sync2?
为什么运行同步2中的setTimeout不能使其一一呈现?

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?

推荐答案

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

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

这段代码:

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

将添加[length] setTimeouts 调用任务队列并随后执行所有任务(0毫秒超时)。只有最后一个操作才会更新屏幕,因为所有超时任务都首先出现在堆栈上(循环之后,任务队列包含[length] setTimeout 调用)。每次超时都执行 drawChartFunc 。现在 drawChartFunc 确实在任务队列上添加了屏幕更新功能,但是剩余的超时优先,因此首先执行下一个超时-屏幕更新功能只能执行之后 [length] setTimeout 调用完成(从任务队列/堆栈中取出)。随后也会执行此操作,但是速度非常快。如果您的眼睛训练有素,可以看到纳秒级的跃迁,那么您可能已经在输出中发现了随后的数字;)

Will add [length] 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 [length] 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 [length] 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 ;)

现在

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

将首先运行 drawChartFunc 将屏幕更新放到任务队列中,然后将增量 i 放到任务队列中,并且-在适用的情况下-之后添加新的 setTimeout 到任务队列。换句话说,将 drawChartFunc 放到堆栈上,这会将屏幕更新放到堆栈上,两个都执行,然后随后超时在堆栈上,将 drawChartFunc 放在堆栈上...等等。

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.

关于javascript任务队列/堆栈: 此视频 对我真的很有帮助。

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

这是您的 jsFiddle ,有点改写。它显示了这两种方法的排队过程。

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

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

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