为什么UI操作在计算之后运行,即使两者交替



我的问题更复杂,但我已经找到了这个简单的&简明示例:

HTML:

First: <span id="first"></span> <br/> 
Then: <span id="second"></span> <br/> 
And then: <span id="third"></span> <br/> 
And then: <span id="fourth"></span> <br/> 
And then: <span id="fifth"></span>

JS(+jQuery(如果重要)):

$(document).ready(function() {
  doStuff();
});
function doStuff() {
  $("#first").text(new Date().getSeconds());
  var i = 1;
  while (i < 1000000000) {
    i++;
  }
  $("#second").text(new Date().getSeconds());
  var i = 1;
  while (i < 1000000000) {
    i++;
  }
  $("#third").text(new Date().getSeconds());
  var i = 1;
  while (i < 1000000000) {
    i++;
  }
  $("#fourth").text(new Date().getSeconds());
  var i = 1;
  while (i < 1000000000) {
    i++;
  }
  $("#fifth").text(new Date().getSeconds());
}

还有小提琴。

从这个例子中,我的直觉告诉我$("#first")应该在$("#fifth")之前接收它的文本值。然而,它们同时出现。不,这不是JS运行非常快的问题,正如您在示例中看到的,$("#first")的值比$("#fifth")低约2秒。

为什么会发生这种情况(以及什么!),存在什么解决方案?

javascript会阻止页面渲染,因此在所有javascript块完成之前,它不会渲染html输出。

JavaScript会在UI完成之前阻止它。它应该是一种单线程语言,然而(正如本文所解释的)它并没有那么简单。

解决您问题的方法是使用setTimeout。请参阅更新后的简化fiddle(该示例不适合复制粘贴,但我相信它足以展示这个想法):

$(document).ready(function() {
  doStuff();
});
function doStuff() {
  $("#first").text(new Date().getSeconds());
  var i = 1;
  setTimeout(function() {
    while (i < 1000000000) {
      i++;
    }
    $("#second").text(new Date().getSeconds());
  }, 0);
}

setTimeout确保doStuff函数完成,然后浏览器处理DOM更改,然后执行另一个函数(传递给setTimeout方法)。

关于事情为什么会以这种方式发生,可以在这里找到一个简洁明了的解释(感谢@bhspencer提供链接)。简单明了:当JS处理doStuff方法时,UI被阻塞(由于其单线程性质)。第二个参数设置为0毫秒的对setTimeout的调用(立即)将另一段代码(setTimeout的第一个参数)放入处理队列。然后doStuff方法结束。然后JS处理队列中的下一个项目,这显然是UI更新。同样,当UI更新完成时,队列中的下一项是setTimout调用添加到那里的内容。

相关内容

最新更新