循环阻止 DOM 在其之前操作代码

Posted

技术标签:

【中文标题】循环阻止 DOM 在其之前操作代码【英文标题】:Loop blocks DOM manipulating code before it 【发布时间】:2019-05-29 21:59:38 【问题描述】:

这里我使用循环代码(借鉴What's the equivalent of Java's Thread.sleep() in javascript?)来模拟网络延迟来检查我的加载动画效果。但是,第一行也被阻塞了 5 秒。而第二行(日志语句)不是。发生了什么事?

  main.innerhtml += '<div id="animation-container"></div>'
  console.log("??????????");

  var e = new Date().getTime() + (5 * 1000);
  while (new Date().getTime() <= e) 

  main.innerHTML += 'real content'

【问题讨论】:

我相信这是因为,虽然 DOM(这是页面内容的 JS 内部表示)是同步更新的,但浏览器只有在所有(同步)JS 代码都具有运行完毕。 to simulate web latency to check my loading animation effect Chrome 的(可能还有 Firefox 的)开发工具内置了这个。不要费心破解你自己的代码来模拟网络延迟,使用开发工具( F12 -> Network -> change “在线”到“3G”) 【参考方案1】:

浏览器在一个线程中运行(它不是,但为了简单起见我们假设)。在该线程上运行多个引擎,一个用于 CSS 和 HTML,一个用于 JavaScript。

 main.innerHTML += '<div id="animation-container"></div>'
console.log("");

这两个语句有很大的不同:日志记录由 JavaScript 引擎完成,而 DOM 突变被发送到 HTML 引擎。现在发送是异步的,因为 HTML 引擎当前没有像 JavaScript 引擎那样运行,因此突变将在某种队列中结束。现在您阻塞了 JavaScript 引擎,因此也阻塞了浏览器线程,因此 HTML 引擎无法获得更新视图的处理时间。

结论:不要编写阻塞式 JavaScript!利用其异步特性和浏览器工具(DevTools > Latency)。

【讨论】:

以上是关于循环阻止 DOM 在其之前操作代码的主要内容,如果未能解决你的问题,请参考以下文章

如何在对象完全加载到$ scope之前阻止DOM加载?

DOM事件绑定与行为阻止

DOM事件绑定与行为阻止

SwiftUI 点击手势阻止列表中的项目删除操作

为啥 Sleep() 函数会阻止整个循环工作?

如何在 Vuex 操作完成之前阻止 Vue 生命周期继续进行?