为什么这段代码不是同步执行的?

Why isn't this code executing synchronously?

我的印象是所有 DOM 操作都是同步的。

但是,此代码并不像我预期的那样 运行。

RecordManager.prototype._instantiateNewRecord = function(node) {
  this.beginLoad(); 
  var new_record = new Record(node.data.fields, this);
  this.endLoad();
};
RecordManager.prototype.beginLoad = function() {
  $(this.loader).removeClass('hidden');
};
RecordManager.prototype.endLoad = function() {
  $(this.loader).addClass('hidden');
};

Record 构造函数非常大,它涉及实例化一大堆 Field 对象,每个对象实例化它们自己的一些其他对象。

这会导致 1-2 秒的延迟,我希望在此延迟期间有一个加载图标,这样页面就不会看起来像冻结了。


我预计事件的流程是:

除了流程最终是:


所以,你根本看不到加载图标,我只知道它正在加载,因为 chrome 开发工具 DOM 查看器的更新有点滞后。

我应该从我的代码中期待这种行为吗?如果是,为什么?

是的,这是意料之中的。尽管 DOM 可能已经更新,但在浏览器有机会重新绘制之前,您不会看到它。重绘将以与所有其他事物在浏览器中排队相同的方式排队(即它不会发生,直到 JavaScript 的当前块完成执行),尽管在调试器中暂停通常会允许它发生.

对于您的情况,您可以使用 setTimeout 立即超时修复它:

RecordManager.prototype._instantiateNewRecord = function(node) {
  this.beginLoad(); 
  setTimeout(function() {
    var new_record = new Record(node.data.fields, this);
    this.endLoad();
  }, 0);
};

这将允许在执行代码的下一部分之前进行重绘。

JavaScript 总是同步的。当涉及到 ajax 调用和计时器时,它 模仿 多线程行为,但是当回调返回时,它将像往常一样阻塞。

就是说,您很可能在某个构造函数中有一个 setTimeout(或者您正在使用的方法)。即使是 setTimeout(fnc, 0).