【问题标题】:Why isn't this code executing synchronously?为什么这段代码不同步执行?
【发布时间】:2015-07-29 19:11:49
【问题描述】:

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

我应该期待我的代码出现这种行为吗?如果有,为什么?

【问题讨论】:

  • 确实是奇怪的行为!你从哪里打电话给_instantiateNewRecord?也许,如果它来自阻塞渲染队列的事件处理程序,您可以异步运行它?

标签: javascript jquery dom asynchronous sync


【解决方案1】:

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

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

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

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

【讨论】:

【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2015-08-31
    • 1970-01-01
    • 2013-06-26
    • 2021-09-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多