浏览器如何执行 Javascript 并异步渲染 [英] How browser executes Javascript and renders asynchronously

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

问题描述

这是jsfiddle上的代码

<div class="row btn_area"><button class="btn btn-info" onclick="updateSync1()">运行同步1</button><button class="btn btn-info" onclick="updateSync2()">运行同步2</button><button class="btn btn-info" onclick="updateAsync()">运行异步</button><span class="label label-info pull-right" style="display:block;"id="输出"></span>

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

当我点击Run Sync 1"时,代码会直接运行到 999.

当我点击'Run Sync 2'时,代码会直接运行到999.

当我点击Run Async"时,页面会一一呈现.

谁能帮忙解释一下 Run Sync1 &运行 Sync2?为什么Run Sync 2中的setTimeout没有让它一一渲染?

解决方案

Javascript 执行是 single-穿线.它使用任务队列和堆栈来执行内容.

这段代码:

for (var i=0;i

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

现在

function updateLater() {drawChartFunc();我++;如果(我<长度){setTimeout(updateLater, 0);}}

将首先运行 drawChartFunc 将屏幕更新放入任务队列,然后将增量 i 放入任务队列,然后 - 如果适用 - 之后添加新的 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?

解决方案

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 [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 ;)

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 并异步渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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