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

时间:2015-07-29 19:11:50

标签: javascript jquery dom asynchronous sync

我的印象是所有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查看器中的更新滞后了一点。

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

2 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:-2)

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

那就是说,你很可能在那个构造函数中有一个get(或者你正在使用的方法)。即使它是setTimeout